diff --git a/.codecov.yml b/.codecov.yml index 0efd75366..fb63b3210 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -5,7 +5,7 @@ coverage: status: patch: default: - target: 76 + target: 55 changes: false project: default: diff --git a/CHANGELOG.md b/CHANGELOG.md index 3237b9f7f..fa2be6d64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ [Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.1.4...1.1.5) __Improvements__ +- Make it easier to use `ParseApple` ([#81](https://github.com/parse-community/Parse-Swift/pull/81)), thanks to [Corey Baker](https://github.com/cbaker6). - `ParseACL` improvements. Only call `ParseUser.current` when necessary ([#80](https://github.com/parse-community/Parse-Swift/pull/80)), thanks to [Corey Baker](https://github.com/cbaker6). ### 1.1.4 diff --git a/Sources/ParseSwift/Authentication/3rd Party/ParseApple.swift b/Sources/ParseSwift/Authentication/3rd Party/ParseApple.swift index eae29aa1a..ef3a333d1 100644 --- a/Sources/ParseSwift/Authentication/3rd Party/ParseApple.swift +++ b/Sources/ParseSwift/Authentication/3rd Party/ParseApple.swift @@ -29,10 +29,13 @@ public struct ParseApple: ParseAuthentication { /// - parameter user: Required id for the user. /// - parameter identityToken: Required identity token for the user. /// - returns: Required authData dictionary. + /// - throws: `ParseError` if the `identityToken` can't be converted + /// to a string. func makeDictionary(user: String, - identityToken: String) -> [String: String] { - [AuthenticationKeys.id.rawValue: user, - AuthenticationKeys.token.rawValue: identityToken] + identityToken: Data) throws -> [String: String] { + let identityTokenString = identityToken.hexEncodedString() + return [AuthenticationKeys.id.rawValue: user, + AuthenticationKeys.token.rawValue: identityTokenString] } /// Verifies all mandatory keys are in authData. @@ -64,14 +67,22 @@ public extension ParseApple { - parameter completion: The block to execute. */ func login(user: String, - identityToken: String, + identityToken: Data, options: API.Options = [], callbackQueue: DispatchQueue = .main, completion: @escaping (Result) -> Void) { - login(authData: AuthenticationKeys.id.makeDictionary(user: user, identityToken: identityToken), - options: options, - callbackQueue: callbackQueue, - completion: completion) + + guard let appleAuthData = try? AuthenticationKeys.id.makeDictionary(user: user, identityToken: identityToken) else { + callbackQueue.async { + completion(.failure(.init(code: .unknownError, + message: "Couldn't create authData."))) + } + return + } + login(authData: appleAuthData, + options: options, + callbackQueue: callbackQueue, + completion: completion) } func login(authData: [String: String]?, @@ -105,10 +116,16 @@ public extension ParseApple { */ @available(macOS 10.15, iOS 13.0, macCatalyst 13.0, watchOS 6.0, tvOS 13.0, *) func loginPublisher(user: String, - identityToken: String, + identityToken: Data, options: API.Options = []) -> Future { - loginPublisher(authData: AuthenticationKeys.id.makeDictionary(user: user, identityToken: identityToken), - options: options) + guard let appleAuthData = try? AuthenticationKeys.id.makeDictionary(user: user, identityToken: identityToken) else { + return Future { promise in + promise(.failure(.init(code: .unknownError, + message: "Couldn't create authData."))) + } + } + return loginPublisher(authData: appleAuthData, + options: options) } @available(macOS 10.15, iOS 13.0, macCatalyst 13.0, watchOS 6.0, tvOS 13.0, *) @@ -142,14 +159,21 @@ public extension ParseApple { - parameter completion: The block to execute. */ func link(user: String, - identityToken: String, + identityToken: Data, options: API.Options = [], callbackQueue: DispatchQueue = .main, completion: @escaping (Result) -> Void) { - link(authData: AuthenticationKeys.id.makeDictionary(user: user, identityToken: identityToken), - options: options, - callbackQueue: callbackQueue, - completion: completion) + guard let appleAuthData = try? AuthenticationKeys.id.makeDictionary(user: user, identityToken: identityToken) else { + callbackQueue.async { + completion(.failure(.init(code: .unknownError, + message: "Couldn't create authData."))) + } + return + } + link(authData: appleAuthData, + options: options, + callbackQueue: callbackQueue, + completion: completion) } func link(authData: [String: String]?, @@ -183,9 +207,15 @@ public extension ParseApple { */ @available(macOS 10.15, iOS 13.0, macCatalyst 13.0, watchOS 6.0, tvOS 13.0, *) func linkPublisher(user: String, - identityToken: String, + identityToken: Data, options: API.Options = []) -> Future { - linkPublisher(authData: AuthenticationKeys.id.makeDictionary(user: user, identityToken: identityToken), + guard let appleAuthData = try? AuthenticationKeys.id.makeDictionary(user: user, identityToken: identityToken) else { + return Future { promise in + promise(.failure(.init(code: .unknownError, + message: "Couldn't create authData."))) + } + } + return linkPublisher(authData: appleAuthData, options: options) } diff --git a/Tests/ParseSwiftTests/ParseAppleCombineTests.swift b/Tests/ParseSwiftTests/ParseAppleCombineTests.swift index 0fd30ec41..ed6e02a2f 100644 --- a/Tests/ParseSwiftTests/ParseAppleCombineTests.swift +++ b/Tests/ParseSwiftTests/ParseAppleCombineTests.swift @@ -112,7 +112,12 @@ class ParseAppleCombineTests: XCTestCase { // swiftlint:disable:this type_body_l return MockURLResponse(data: encoded, statusCode: 200, delay: 0.0) } - let publisher = User.apple.loginPublisher(user: "testing", identityToken: "this") + guard let tokenData = "this".data(using: .utf8) else { + XCTFail("Couldn't convert token data to string") + return + } + + let publisher = User.apple.loginPublisher(user: "testing", identityToken: tokenData) .sink(receiveCompletion: { result in if case let .failure(error) = result { @@ -172,7 +177,12 @@ class ParseAppleCombineTests: XCTestCase { // swiftlint:disable:this type_body_l return MockURLResponse(data: encoded, statusCode: 200, delay: 0.0) } - let publisher = User.apple.linkPublisher(user: "testing", identityToken: "this") + guard let tokenData = "this".data(using: .utf8) else { + XCTFail("Couldn't convert token data to string") + return + } + + let publisher = User.apple.linkPublisher(user: "testing", identityToken: tokenData) .sink(receiveCompletion: { result in if case let .failure(error) = result { @@ -201,9 +211,14 @@ class ParseAppleCombineTests: XCTestCase { // swiftlint:disable:this type_body_l _ = try loginNormally() MockURLProtocol.removeAll() - let authData = ParseApple + guard let tokenData = "this".data(using: .utf8) else { + XCTFail("Couldn't convert token data to string") + return + } + + let authData = try ParseApple .AuthenticationKeys.id.makeDictionary(user: "testing", - identityToken: "this") + identityToken: tokenData) User.current?.authData = [User.apple.__type: authData] XCTAssertTrue(User.apple.isLinked) diff --git a/Tests/ParseSwiftTests/ParseAppleTests.swift b/Tests/ParseSwiftTests/ParseAppleTests.swift index 36481ab9f..fcf912396 100644 --- a/Tests/ParseSwiftTests/ParseAppleTests.swift +++ b/Tests/ParseSwiftTests/ParseAppleTests.swift @@ -94,17 +94,23 @@ class ParseAppleTests: XCTestCase { } func testAuthenticationKeys() throws { - let authData = ParseApple + let tokenData = Data([0, 1, 127, 128, 255]) + let authData = try ParseApple .AuthenticationKeys.id.makeDictionary(user: "testing", - identityToken: "this") - XCTAssertEqual(authData, ["id": "testing", "token": "this"]) + identityToken: tokenData) + XCTAssertEqual(authData, ["id": "testing", "token": "00017f80ff"]) } func testLogin() throws { var serverResponse = LoginSignupResponse() - let authData = ParseApple + guard let tokenData = "this".data(using: .utf8) else { + XCTFail("Couldn't convert token data to string") + return + } + + let authData = try ParseApple .AuthenticationKeys.id.makeDictionary(user: "testing", - identityToken: "this") + identityToken: tokenData) serverResponse.username = "hello" serverResponse.password = "world" serverResponse.objectId = "yarr" @@ -130,7 +136,7 @@ class ParseAppleTests: XCTestCase { let expectation1 = XCTestExpectation(description: "Login") - User.apple.login(user: "testing", identityToken: "this") { result in + User.apple.login(user: "testing", identityToken: tokenData) { result in switch result { case .success(let user): @@ -190,9 +196,14 @@ class ParseAppleTests: XCTestCase { func testReplaceAnonymousWithApple() throws { try loginAnonymousUser() MockURLProtocol.removeAll() - let authData = ParseApple + guard let tokenData = "this".data(using: .utf8) else { + XCTFail("Couldn't convert token data to string") + return + } + + let authData = try ParseApple .AuthenticationKeys.id.makeDictionary(user: "testing", - identityToken: "this") + identityToken: tokenData) var serverResponse = LoginSignupResponse() serverResponse.username = "hello" @@ -220,7 +231,7 @@ class ParseAppleTests: XCTestCase { let expectation1 = XCTestExpectation(description: "Login") - User.apple.login(user: "testing", identityToken: "this") { result in + User.apple.login(user: "testing", identityToken: tokenData) { result in switch result { case .success(let user): @@ -261,7 +272,12 @@ class ParseAppleTests: XCTestCase { let expectation1 = XCTestExpectation(description: "Login") - User.apple.link(user: "testing", identityToken: "this") { result in + guard let tokenData = "this".data(using: .utf8) else { + XCTFail("Couldn't convert token data to string") + return + } + + User.apple.link(user: "testing", identityToken: tokenData) { result in switch result { case .success(let user): @@ -303,7 +319,12 @@ class ParseAppleTests: XCTestCase { let expectation1 = XCTestExpectation(description: "Login") - User.apple.link(user: "testing", identityToken: "this") { result in + guard let tokenData = "this".data(using: .utf8) else { + XCTFail("Couldn't convert token data to string") + return + } + + User.apple.link(user: "testing", identityToken: tokenData) { result in switch result { case .success(let user): @@ -324,9 +345,14 @@ class ParseAppleTests: XCTestCase { func testUnlink() throws { _ = try loginNormally() MockURLProtocol.removeAll() - let authData = ParseApple + guard let tokenData = "this".data(using: .utf8) else { + XCTFail("Couldn't convert token data to string") + return + } + + let authData = try ParseApple .AuthenticationKeys.id.makeDictionary(user: "testing", - identityToken: "this") + identityToken: tokenData) User.current?.authData = [User.apple.__type: authData] XCTAssertTrue(User.apple.isLinked)