diff --git a/.codecov.yml b/.codecov.yml index fd2c86e08..750b282ae 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -6,7 +6,7 @@ coverage: status: patch: default: - target: auto + target: 83 changes: false project: default: diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c1797953..20b143a1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,14 @@ # Parse-Swift Changelog ### main -[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.9.2...main) +[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.9.3...main) * _Contributing to this repo? Add info about your change here to be included in the next release_ +### 4.9.3 +[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.9.2...4.9.3) +__Fixes__ +- Default to not setting kSecUseDataProtectionKeychain to true as this can cause issues with querying the Keychain in Swift Playgrounds or other apps that cannot setup the Keychain on macOS. This behavior can be changed by setting usingDataProtectionKeychain to true when initializing the SDK ([#398](https://github.com/parse-community/Parse-Swift/pull/398)), thanks to [Corey Baker](https://github.com/cbaker6). + ### 4.9.2 [Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.9.1...4.9.2) diff --git a/ParseSwift.playground/Sources/Common.swift b/ParseSwift.playground/Sources/Common.swift index f0d166f39..384f7fc8a 100644 --- a/ParseSwift.playground/Sources/Common.swift +++ b/ParseSwift.playground/Sources/Common.swift @@ -7,5 +7,6 @@ public func initializeParse(customObjectId: Bool = false) { masterKey: "masterKey", serverURL: URL(string: "http://localhost:1337/1")!, allowingCustomObjectIds: customObjectId, - usingEqualQueryConstraint: false) + usingEqualQueryConstraint: false, + usingDataProtectionKeychain: false) } diff --git a/Sources/ParseSwift/Parse.swift b/Sources/ParseSwift/Parse.swift index 24644aa35..c57fd64d5 100644 --- a/Sources/ParseSwift/Parse.swift +++ b/Sources/ParseSwift/Parse.swift @@ -26,6 +26,7 @@ internal func initialize(applicationId: String, cacheMemoryCapacity: Int = 512_000, cacheDiskCapacity: Int = 10_000_000, migratingFromObjcSDK: Bool = false, + usingDataProtectionKeychain: Bool = false, deletingKeychainIfNeeded: Bool = false, httpAdditionalHeaders: [AnyHashable: Any]? = nil, maxConnectionAttempts: Int = 5, @@ -46,6 +47,7 @@ internal func initialize(applicationId: String, requestCachePolicy: requestCachePolicy, cacheMemoryCapacity: cacheMemoryCapacity, cacheDiskCapacity: cacheDiskCapacity, + usingDataProtectionKeychain: usingDataProtectionKeychain, deletingKeychainIfNeeded: deletingKeychainIfNeeded, httpAdditionalHeaders: httpAdditionalHeaders, maxConnectionAttempts: maxConnectionAttempts, @@ -191,6 +193,8 @@ public func initialize(configuration: ParseConfiguration) { for more info. - parameter cacheMemoryCapacity: The memory capacity of the cache, in bytes. Defaults to 512KB. - parameter cacheDiskCapacity: The disk capacity of the cache, in bytes. Defaults to 10MB. + - parameter usingDataProtectionKeychain: Sets `kSecUseDataProtectionKeychain` to **true**. See Apple's [documentation](https://developer.apple.com/documentation/security/ksecusedataprotectionkeychain) + for more info. Defaults to **false**. - parameter deletingKeychainIfNeeded: Deletes the Parse Keychain when the app is running for the first time. Defaults to **false**. - parameter httpAdditionalHeaders: A dictionary of additional headers to send with requests. See Apple's @@ -201,9 +205,11 @@ public func initialize(configuration: ParseConfiguration) { It should have the following argument signature: `(challenge: URLAuthenticationChallenge, completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. - - warning: `usingTransactions` is experimental. - warning: It is recomended to only specify `masterKey` when using the SDK on a server. Do not use this key on the client. + - warning: `usingTransactions` is experimental. - warning: Setting `usingPostForQuery` to **true** will require all queries to access the server instead of following the `requestCachePolicy`. + - warning: Setting `usingDataProtectionKeychain` to **true** is known to cause issues in Playgrounds or in + situtations when apps do not have credentials to setup a Keychain. */ public func initialize( applicationId: String, @@ -219,6 +225,7 @@ public func initialize( requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, cacheMemoryCapacity: Int = 512_000, cacheDiskCapacity: Int = 10_000_000, + usingDataProtectionKeychain: Bool = false, deletingKeychainIfNeeded: Bool = false, httpAdditionalHeaders: [AnyHashable: Any]? = nil, maxConnectionAttempts: Int = 5, @@ -239,6 +246,7 @@ public func initialize( requestCachePolicy: requestCachePolicy, cacheMemoryCapacity: cacheMemoryCapacity, cacheDiskCapacity: cacheDiskCapacity, + usingDataProtectionKeychain: usingDataProtectionKeychain, deletingKeychainIfNeeded: deletingKeychainIfNeeded, httpAdditionalHeaders: httpAdditionalHeaders, maxConnectionAttempts: maxConnectionAttempts, @@ -272,6 +280,8 @@ public func initialize( - parameter cacheDiskCapacity: The disk capacity of the cache, in bytes. Defaults to 10MB. - parameter migratingFromObjcSDK: If your app previously used the iOS Objective-C SDK, setting this value to **true** will attempt to migrate relevant data stored in the Keychain to ParseSwift. Defaults to **false**. + - parameter usingDataProtectionKeychain: Sets `kSecUseDataProtectionKeychain` to **true**. See Apple's [documentation](https://developer.apple.com/documentation/security/ksecusedataprotectionkeychain) + for more info. Defaults to **false**. - parameter deletingKeychainIfNeeded: Deletes the Parse Keychain when the app is running for the first time. Defaults to **false**. - parameter httpAdditionalHeaders: A dictionary of additional headers to send with requests. See Apple's @@ -282,9 +292,11 @@ public func initialize( It should have the following argument signature: `(challenge: URLAuthenticationChallenge, completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. - - warning: `usingTransactions` is experimental. - warning: It is recomended to only specify `masterKey` when using the SDK on a server. Do not use this key on the client. + - warning: `usingTransactions` is experimental. - warning: Setting `usingPostForQuery` to **true** will require all queries to access the server instead of following the `requestCachePolicy`. + - warning: Setting `usingDataProtectionKeychain` to **true** is known to cause issues in Playgrounds or in + situtations when apps do not have credentials to setup a Keychain. */ @available(*, deprecated, message: "Remove the migratingFromObjcSDK argument") public func initialize( @@ -302,6 +314,7 @@ public func initialize( cacheMemoryCapacity: Int = 512_000, cacheDiskCapacity: Int = 10_000_000, migratingFromObjcSDK: Bool = false, + usingDataProtectionKeychain: Bool = false, deletingKeychainIfNeeded: Bool = false, httpAdditionalHeaders: [AnyHashable: Any]? = nil, maxConnectionAttempts: Int = 5, @@ -322,6 +335,7 @@ public func initialize( requestCachePolicy: requestCachePolicy, cacheMemoryCapacity: cacheMemoryCapacity, cacheDiskCapacity: cacheDiskCapacity, + usingDataProtectionKeychain: usingDataProtectionKeychain, deletingKeychainIfNeeded: deletingKeychainIfNeeded, httpAdditionalHeaders: httpAdditionalHeaders, maxConnectionAttempts: maxConnectionAttempts, diff --git a/Sources/ParseSwift/Storage/KeychainStore.swift b/Sources/ParseSwift/Storage/KeychainStore.swift index 637478da6..46f8125b7 100644 --- a/Sources/ParseSwift/Storage/KeychainStore.swift +++ b/Sources/ParseSwift/Storage/KeychainStore.swift @@ -130,7 +130,7 @@ struct KeychainStore: SecureStorage { query[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly as String } #if os(macOS) - if !Parse.configuration.isTestingSDK { + if Parse.configuration.isUsingDataProtectionKeychain { query[kSecUseDataProtectionKeychain as String] = kCFBooleanTrue } #endif diff --git a/Sources/ParseSwift/Types/ParseConfiguration.swift b/Sources/ParseSwift/Types/ParseConfiguration.swift index 2b00d4ec1..1d6a9d9b6 100644 --- a/Sources/ParseSwift/Types/ParseConfiguration.swift +++ b/Sources/ParseSwift/Types/ParseConfiguration.swift @@ -77,6 +77,13 @@ public struct ParseConfiguration { /// Defaults to **false**. public internal(set) var isDeletingKeychainIfNeeded: Bool = false + /// Sets `kSecUseDataProtectionKeychain` to **true**. See Apple's [documentation](https://developer.apple.com/documentation/security/ksecusedataprotectionkeychain) + /// for more info. + /// Defaults to **false**. + /// - warning: This is known to cause issues in Playgrounds or in situtations when + /// apps do not have credentials to setup a Keychain. + public internal(set) var isUsingDataProtectionKeychain: Bool = false + /// Maximum number of times to try to connect to Parse Server. /// Defaults to 5. public internal(set) var maxConnectionAttempts: Int = 5 @@ -115,6 +122,8 @@ public struct ParseConfiguration { - parameter cacheDiskCapacity: The disk capacity of the cache, in bytes. Defaults to 10MB. - parameter migratingFromObjcSDK: If your app previously used the iOS Objective-C SDK, setting this value to **true** will attempt to migrate relevant data stored in the Keychain to ParseSwift. Defaults to **false**. + - parameter usingDataProtectionKeychain: Sets `kSecUseDataProtectionKeychain` to **true**. See Apple's [documentation](https://developer.apple.com/documentation/security/ksecusedataprotectionkeychain) + for more info. Defaults to **false**. - parameter deletingKeychainIfNeeded: Deletes the Parse Keychain when the app is running for the first time. Defaults to **false**. - parameter httpAdditionalHeaders: A dictionary of additional headers to send with requests. See Apple's @@ -127,9 +136,11 @@ public struct ParseConfiguration { It should have the following argument signature: `(challenge: URLAuthenticationChallenge, completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. - - warning: `usingTransactions` is experimental. - warning: It is recomended to only specify `masterKey` when using the SDK on a server. Do not use this key on the client. + - warning: `usingTransactions` is experimental. - warning: Setting `usingPostForQuery` to **true** will require all queries to access the server instead of following the `requestCachePolicy`. + - warning: Setting `usingDataProtectionKeychain` to **true** is known to cause issues in Playgrounds or in + situtations when apps do not have credentials to setup a Keychain. */ public init(applicationId: String, clientKey: String? = nil, @@ -145,6 +156,7 @@ public struct ParseConfiguration { requestCachePolicy: URLRequest.CachePolicy = .useProtocolCachePolicy, cacheMemoryCapacity: Int = 512_000, cacheDiskCapacity: Int = 10_000_000, + usingDataProtectionKeychain: Bool = false, deletingKeychainIfNeeded: Bool = false, httpAdditionalHeaders: [AnyHashable: Any]? = nil, maxConnectionAttempts: Int = 5, @@ -167,6 +179,7 @@ public struct ParseConfiguration { self.requestCachePolicy = requestCachePolicy self.cacheMemoryCapacity = cacheMemoryCapacity self.cacheDiskCapacity = cacheDiskCapacity + self.isUsingDataProtectionKeychain = usingDataProtectionKeychain self.isDeletingKeychainIfNeeded = deletingKeychainIfNeeded self.httpAdditionalHeaders = httpAdditionalHeaders self.maxConnectionAttempts = maxConnectionAttempts @@ -198,6 +211,8 @@ public struct ParseConfiguration { - parameter cacheDiskCapacity: The disk capacity of the cache, in bytes. Defaults to 10MB. - parameter migratingFromObjcSDK: If your app previously used the iOS Objective-C SDK, setting this value to **true** will attempt to migrate relevant data stored in the Keychain to ParseSwift. Defaults to **false**. + - parameter usingDataProtectionKeychain: Sets `kSecUseDataProtectionKeychain` to **true**. See Apple's [documentation](https://developer.apple.com/documentation/security/ksecusedataprotectionkeychain) + for more info. Defaults to **false**. - parameter deletingKeychainIfNeeded: Deletes the Parse Keychain when the app is running for the first time. Defaults to **false**. - parameter httpAdditionalHeaders: A dictionary of additional headers to send with requests. See Apple's @@ -210,9 +225,11 @@ public struct ParseConfiguration { It should have the following argument signature: `(challenge: URLAuthenticationChallenge, completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void`. See Apple's [documentation](https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411595-urlsession) for more for details. - - warning: `usingTransactions` is experimental. - warning: It is recomended to only specify `masterKey` when using the SDK on a server. Do not use this key on the client. + - warning: `usingTransactions` is experimental. - warning: Setting `usingPostForQuery` to **true** will require all queries to access the server instead of following the `requestCachePolicy`. + - warning: Setting `usingDataProtectionKeychain` to **true** is known to cause issues in Playgrounds or in + situtations when apps do not have credentials to setup a Keychain. */ @available(*, deprecated, message: "Remove the migratingFromObjcSDK argument") public init(applicationId: String, @@ -230,6 +247,7 @@ public struct ParseConfiguration { cacheMemoryCapacity: Int = 512_000, cacheDiskCapacity: Int = 10_000_000, migratingFromObjcSDK: Bool = false, + usingDataProtectionKeychain: Bool = false, deletingKeychainIfNeeded: Bool = false, httpAdditionalHeaders: [AnyHashable: Any]? = nil, maxConnectionAttempts: Int = 5, @@ -250,6 +268,7 @@ public struct ParseConfiguration { requestCachePolicy: requestCachePolicy, cacheMemoryCapacity: cacheMemoryCapacity, cacheDiskCapacity: cacheDiskCapacity, + usingDataProtectionKeychain: usingDataProtectionKeychain, deletingKeychainIfNeeded: deletingKeychainIfNeeded, httpAdditionalHeaders: httpAdditionalHeaders, maxConnectionAttempts: maxConnectionAttempts,