Skip to content

Add ability to transform values on migrate#228

Merged
dfed merged 12 commits intomasterfrom
dfed--transform-on-migrate
Jun 22, 2020
Merged

Add ability to transform values on migrate#228
dfed merged 12 commits intomasterfrom
dfed--transform-on-migrate

Conversation

@dfed
Copy link
Copy Markdown
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.

}
}

func test_migrateObjectsMatching_withAccountNameAsData_doesNotRaiseException() throws
Copy link
Copy Markdown
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
Copy Markdown

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%> (ø)

var keysToMigrate = Set<String>()
var keyValuePairsToMigrate = [String: Data]()
for keychainEntry in retrievedItemsToMigrateWithData {
guard let key = keychainEntry[kSecAttrAccount as String] as? String, key != Keychain.canaryKey else {
Copy link
Copy Markdown
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 NickEntin and fdiaz 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
XCTAssertNil(valet);
}

- (void)test_containsObjectForKey_returnsTrueWhenObjectExistsInKeychain;
Copy link
Copy Markdown
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


- (BOOL)testEnvironmentIsSigned;
{
return NSBundle.mainBundle.bundleIdentifier != nil && ![NSBundle.mainBundle.bundleIdentifier isEqualToString:@"com.apple.dt.xctest.tool"];
Copy link
Copy Markdown
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
}


func test_migrateObjectsMatchingCompactMap_successfullyMigratesTransformedValue() throws {
Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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