-
Notifications
You must be signed in to change notification settings - Fork 53
[BITAU-137] Create AuthenticatorSyncKit SDK #913
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
[BITAU-137] Create AuthenticatorSyncKit SDK #913
Conversation
No New Or Fixed Issues Found |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #913 +/- ##
==========================================
+ Coverage 88.62% 88.64% +0.01%
==========================================
Files 620 621 +1
Lines 39200 39261 +61
==========================================
+ Hits 34742 34803 +61
Misses 4458 4458 ☔ View full report in Codecov by Sentry. |
#include "./Common.xcconfig" | ||
#include? "./Local.xcconfig" | ||
|
||
PRODUCT_BUNDLE_IDENTIFIER = $(ORGANIZATION_IDENTIFIER).AuthenticatorSyncShared |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎨 All of our other bundle IDs are kebab-cased as near as I can tell; it probably makes sense for us to continue that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in next commit. 👍
project.yml
Outdated
@@ -55,12 +55,14 @@ schemes: | |||
- BitwardenAutoFillExtension | |||
- BitwardenShareExtension | |||
- BitwardenShared | |||
- AuthenticatorSyncShared |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎨 Can this be alphabetized?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume you mean the whole file? (i.e. it should be the first target as well). I'll have it updated to that in the next commit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're not the most consistent about alphabetization with the targets (notably, we put BitwardenTests
after Bitwarden
but before BitwardenActionExtension
), but yeah, in general if we have a list of things that doesn't have an enforced order, by convention we like to alphabetize them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated in the latest commit. Let me know if we need to adjust anything else 👍
Package.swift
Outdated
], | ||
products: [ | ||
.library( | ||
name: "AuthenticatorSyncShared", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 I'm not super in love with this name, though I can't think of anything better. Just, if in the future we want to put more things in a shared library between the Password Manager and Authenticator apps, keeping it in the same package makes sense, but the name might not at that point. Probably moot, realistically, but something to think about
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 I see your point. We could possibly name it like the App Group and go with BitwardenAuthenticatorShared
? That would simply imply where it's used (in both apps) rather than relating it just to sync.
Alternatively, we could keep this one scoped to just Sync (maybe even name it simply SyncShared) and set a pattern for future packages to be targeted to just one feature? i.e. The main package right now is BitwardenShared, but we are only sharing one product (AuthenticatorSyncShared
). If you wanted to share Feature X in the future, you could make a FeatureXShared product/target and share via this same mechanism, rather than putting it also in the same product to share. That would add a bit more on the Authenticator side, however, as you'd need to explicitly pull in each product that you're interested in using.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. I see merits to both approaches. If we did it by-feature, I'd suggest actually maybe AuthenticationSyncShared
, so that it's more clearly "this is syncing authentication things".
But also having a broader one that makes it easier in the future for us to just move things from BitwardenShared
to it in order to share between the two projects... (though personally, I would have called that BitwardenShared
so I don't know 😂 )
@fedemkr Do you have a strong opinion on whether we want to name more broadly or do a per-feature naming, or something else entirely?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming is hard, can't think of a really good name for this 🤔 .
I think it depends on the scope (and possible future scope) of this. I would guess that what we're possibly going to share between the two apps would be auth data and syncing the vault.
Additionally, I wouldn't put general "helpers" or controls shared between any potential apps as I would add these kind of stuff to an independent package we can reuse amongst all current/future apps without nothing specific of a particular one, e.g. we could also potentially use this future package on the Watch app (I guess for now it doesn't hurt much adding this here until we have the independent package if we really need to)
Having said this I'm fine with the particular naming for now to denote what the package is about and helps not to include general stuff in there (unless really needed). Furthermore, we can revisit the naming while we include stuff if needed.
I thought about the next ones but not strongly in favor of any of these nor thinking they're better than the original one, although don't really like much the suffix Shared
as we're using that for internal targets:
AuthenticatorSyncCore
AuthenticatorSyncEngine
AuthenticatorSyncManager
AuthenticatorSyncKit
AuthenticatorSyncFoundation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm only a little cautious about naming here because changing the name of a package like this, when it's shared, could be mildly disruptive between the two projects.
I do actually like Kit
as a suffix; that's something I've used before for this sort of thing, now that I think about it, and it's kind of how Apple likes it. AuthenticationSyncKit
? AuthenticatorSyncKit
? Something like that seems like it would be good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, yesterday reviewed Apple's naming and Kit
and Foundation
are usually used as suffixes 😄 . Totally agree let's go with AuthenticatorSyncKit
😄 (I wouldn't go for Authentication
given that if I recall correctly this would also allow the app to send ciphers from one place to the other)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me as well - I'll migrate to AuthenticatorSyncKit
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@KatherineInCode @fedemkr OK, I think I've got all the names changed over. Latest commit should have everything running with the new name. But do be on the lookout for anything I might have missed.
|
||
// MARK: Methods | ||
|
||
/// Retrieve the value for the specifi item from the Keychain Service. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ Typo
/// Retrieve the value for the specifi item from the Keychain Service. | |
/// Retrieve the value for the specific item from the Keychain Service. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 will fix in next commit
if let resultDictionary = foundItem as? [String: Any], | ||
let data = resultDictionary[kSecValueData as String] as? Data { | ||
return data | ||
} else { | ||
throw AuthenticatorKeychainServiceError.keyNotFound(item) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ Invert using guard
to avoid extra branches:
if let resultDictionary = foundItem as? [String: Any], | |
let data = resultDictionary[kSecValueData as String] as? Data { | |
return data | |
} else { | |
throw AuthenticatorKeychainServiceError.keyNotFound(item) | |
} | |
guard let resultDictionary = foundItem as? [String: Any], | |
let data = resultDictionary[kSecValueData as String] as? Data else { | |
throw AuthenticatorKeychainServiceError.keyNotFound(item) | |
} | |
return data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 will fix in next commit
|
||
@testable import AuthenticatorSyncShared | ||
|
||
final class SharedKeychainRepositoryTests: XCTestCase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 Could we add a base class for XCTestCase
and get some of BitwardenTestCase methods into it? Like assertAsyncThrows
which are really handy to use. Additionally, I'd like to have a base class for tests in case we need to do changes affecting the entire test suite.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good. I was trying to make sure we didn't duplicate too much, but totally understand wanting to have one base class to work from 👍 assertAsyncThrows
will definitely be handy to have. I'll add in the next commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this in the latest commit. I took out the UI-related stuff (partially because we don't have UI for this in the package, but also because that had some BitwardenShared dependencies as well).
do { | ||
_ = try await subject.getAuthenticatorKey() | ||
XCTFail("Expected error `keyNotFound` was never thrown!") | ||
} catch let caughtError as AuthenticatorKeychainServiceError { | ||
XCTAssertEqual(caughtError, error) | ||
} catch let caughtError { | ||
XCTFail( | ||
"The error caught (\(caughtError)) does not match the type of error provided (\(error))." | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎨 assertAsyncThrows
can be used instead of this to be more clean leveraging the new AuthenticatorSyncSharedTestCase
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be updated in the latest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, just a few tests missing.
|
||
guard let resultDictionary = foundItem as? [String: Any], | ||
let data = resultDictionary[kSecValueData as String] as? Data else { | ||
throw AuthenticatorKeychainServiceError.keyNotFound(item) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ Could tests be added for when foundItem
is not [String: Any]
and another one for when resultDictionary[kSecValueData as String]
is not of Data
type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch 👍 Added those in the latest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome thanks! Sorry but I've just realized of something else I didn't see in the past reviews regarding test naming.
|
||
/// Verify that `deleteAuthenticatorKey()` issues a delete with the correct search attributes specified. | ||
/// | ||
func testDeleteAuthenticatorKey() async throws { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎨 Use the same naming as we do in the main app:
test_{subjectFuncName}_{additionalContext}
So in this case it would be:
test_deleteAuthenticatorKey_success()
This also applies to the other tests in this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 should be fixed in latest
…at we're not ready for release.
80f221e
@fedemkr @victor-livefront Sorry, I realized right before merging that we should have a bundle version of This dismissed your approvals, so I'll need a re-approval before I merge. |
🎟️ Tracking
BITAU-137
📔 Objective
This PR adds the basic structure for sharing an
AuthenticatorSyncShared
Swift package from the main PM app repo. This allows us to share all of the code between the PM and Authenticator apps for building the sync feature, but doesn't require us to make a whole new git repo for managing it (it is simply shared from this repo).This PR is just about getting the basic structure set up correctly and getting feedback on this approach. However, there is the first piece of shared code
SharedKeychainRepository
which adds the ability to read/write keys in the shared keychain via the App Group.The next step after this PR is merged would then be a PR from the Authenticator repo to pull in this via Swift Package.
⏰ Reminders before review
🦮 Reviewer guidelines
:+1:
) or similar for great changes:memo:
) or ℹ️ (:information_source:
) for notes or general info:question:
) for questions:thinking:
) or 💭 (:thought_balloon:
) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion:art:
) for suggestions / improvements:x:
) or:warning:
) for more significant problems or concerns needing attention:seedling:
) or ♻️ (:recycle:
) for future improvements or indications of technical debt:pick:
) for minor or nitpick changes