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

Add ability to transform values on migrate #228

Merged
merged 12 commits into from
Jun 22, 2020
Merged

Conversation

dfed
Copy link
Collaborator

@dfed dfed commented May 20, 2020

This PR resolves #226 by adding the ability to compactMap over key:value pairs as they are being migrated.

I do not intend to merge this PR prior to the release of Valet 4.0.

@@ -708,7 +708,7 @@ class ValetIntegrationTests: XCTestCase
}
}

func test_migrateObjectsMatching_withAccountNameAsData_doesNotRaiseException() throws
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This test name was incorrect.

@dfed dfed changed the title [Draft][RFC] Add ability to transform values on migrate [Draft] Add ability to transform values on migrate May 20, 2020
@codecov-commenter
Copy link

codecov-commenter commented May 20, 2020

Codecov Report

Merging #228 into master will increase coverage by 1.06%.
The diff coverage is 93.90%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #228      +/-   ##
==========================================
+ Coverage   85.68%   86.74%   +1.06%     
==========================================
  Files          15       16       +1     
  Lines         992     1049      +57     
==========================================
+ Hits          850      910      +60     
+ Misses        142      139       -3     
Impacted Files Coverage Δ
Sources/Valet/Internal/Keychain.swift 89.50% <88.88%> (+1.14%) ⬆️
Sources/Valet/Valet.swift 90.74% <95.83%> (+1.71%) ⬆️
Sources/Valet/MigratableKeyValuePair.swift 100.00% <100.00%> (ø)

for keychainEntry in retrievedItemsToMigrateWithData {
guard let key = keychainEntry[kSecAttrAccount as String] as? String, key != Keychain.canaryKey else {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We'll force the key to be a String later on as part of the compactMap. For now, we just want to make sure we have a key.

@dfed dfed requested review from fdiaz and NickEntin May 20, 2020 20:16
@dfed dfed marked this pull request as ready for review May 20, 2020 20:16
@dfed dfed changed the title [Draft] Add ability to transform values on migrate Add ability to transform values on migrate May 20, 2020
@dfed dfed force-pushed the dfed--transform-on-migrate branch from fddf1ce to 9ed7cd6 Compare May 20, 2020 20:22
@@ -167,6 +172,271 @@ - (void)test_iCloudValetWithSharedAccessGroupIdentifier_accessibility_returnsNil
XCTAssertNil(valet);
}

- (void)test_containsObjectForKey_returnsTrueWhenObjectExistsInKeychain;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I realized while I was here that I didn’t have an explicit objective-c test for this wrapper method, so I wrote a couple

@@ -45,6 +45,11 @@ - (NSString *)sharedAccessGroupIdentifier;
#endif
}

- (BOOL)testEnvironmentIsSigned;
{
return NSBundle.mainBundle.bundleIdentifier != nil && ![NSBundle.mainBundle.bundleIdentifier isEqualToString:@"com.apple.dt.xctest.tool"];
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This logic is the same logic used in the swift tests

@dfed dfed linked an issue May 21, 2020 that may be closed by this pull request
@dfed dfed self-assigned this May 21, 2020
README.md Outdated Show resolved Hide resolved
Sources/Valet/Internal/Keychain.swift Outdated Show resolved Hide resolved
Tests/ValetIntegrationTests/KeychainIntegrationTests.swift Outdated Show resolved Hide resolved
Tests/ValetIntegrationTests/KeychainIntegrationTests.swift Outdated Show resolved Hide resolved
@@ -732,7 +732,130 @@ class ValetIntegrationTests: XCTestCase
XCTAssertEqual(error as? MigrationError, .keyToMigrateInvalid)
}
}


func test_migrateObjectsMatchingCompactMap_successfullyMigratesTransformedValue() throws {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we also add a test that transforms the key? (Same for the Valet -> Valet equivalent below)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good call! Will add

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Tests/ValetIntegrationTests/ValetIntegrationTests.swift Outdated Show resolved Hide resolved
Tests/ValetIntegrationTests/ValetIntegrationTests.swift Outdated Show resolved Hide resolved
Sources/Valet/Valet.swift Outdated Show resolved Hide resolved
Sources/Valet/Valet.swift Outdated Show resolved Hide resolved
Sources/Valet/Valet.swift Outdated Show resolved Hide resolved
Copy link
Collaborator

@fdiaz fdiaz left a comment

Choose a reason for hiding this comment

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

I mostly looked at the public API 😉

import Foundation

/// A struct that represented a key:value pair that can be migrated.
public struct MigratableKeyValuePair<KeyType: Hashable>: Hashable {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe?

Suggested change
public struct MigratableKeyValuePair<KeyType: Hashable>: Hashable {
public struct MigratableKeyValuePair<Key: Hashable>: Hashable {

https://swift.org/documentation/api-design-guidelines#name-according-to-roles


/// A sentinal `ObjectiveCCompatibilityMigratableKeyValuePairOutput` that conveys that the migration should be prevented.
@objc
public static func preventMigration() -> ObjectiveCCompatibilityMigratableKeyValuePairOutput {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This method sounds to me more than its actually doing the action to prevent migration on an instance rather than creating an instance that prevents the migration.

Maybe migrationDisabled / migrationPrevented?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah the tough thing here is it isn't super clear that we're doing this work before the migration has started. This is why I wanted to use a future tense. A past-tense phrase here might make it read as if returning it prevented/disabled the migration of just this pair (or future pairs).

In the context where it's used, I hope this method reads well:

[otherValet migrateObjectsMatching:@{
(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService : @"VAL_VALValet_initWithIdentifier:accessibility:_identifier_AccessibleWhenUnlocked",
} compactMap:^VALMigratableKeyValuePairOutput * _Nullable(VALMigratableKeyValuePairInput * _Nonnull input) {
if ([input.key isEqualToString:key1]) {
return [[VALMigratableKeyValuePairOutput alloc] initWithKey:input.key value:input.value];;
} else {
return VALMigratableKeyValuePairOutput.preventMigration;
}
} error:nil];

The documentation on the migrateObjectsMatching Objective-C method also makes it clear how to use this method:

/// Migrates objects matching the input query into the receiving Valet instance.
/// - Parameters:
/// - query: The query with which to retrieve existing keychain data via a call to SecItemCopyMatching.
/// - compactMap: A closure that transforms a key:value pair from the raw pair currently in the keychain into a key:value pair we'll insert into the destination Valet. Returning `nil` from this closure will cause that key:value pair not to be migrated. Returning `VALMigratableKeyValuePairOutput.preventMigration` will prevent migrating any key:value pairs.
/// - error: An error of type `KeychainError` or `MigrationError`.
@available(swift, obsoleted: 1.0)
@objc(migrateObjectsMatching:compactMap:error:)
public func 🚫swift_migrateObjects(matching query: [String : AnyHashable], compactMap: (ObjectiveCCompatibilityMigratableKeyValuePairInput) -> ObjectiveCCompatibilityMigratableKeyValuePairOutput?) throws {

While I agree that reading this method by itself is a bit confusing, I think within the context it's supposed to be used it makes sense? Let me know if not @fdiaz.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That said, I should make this method available only to Objective-C

Base automatically changed from develop--4.0 to master June 13, 2020 23:33
@dfed dfed force-pushed the dfed--transform-on-migrate branch from 093d029 to abb6d42 Compare June 13, 2020 23:42
@dfed
Copy link
Collaborator Author

dfed commented Jun 13, 2020

Force push had no functional changes. Only change was branch history after merging develop--4.0 into master

@dfed dfed merged commit 1879bdb into master Jun 22, 2020
@dfed dfed deleted the dfed--transform-on-migrate branch June 22, 2020 00:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support arbitrary transforms of data during migration
4 participants