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

Improve AppleAuthentication #81

Merged
merged 6 commits into from
Feb 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ coverage:
status:
patch:
default:
target: 76
target: 55
changes: false
project:
default:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
66 changes: 48 additions & 18 deletions Sources/ParseSwift/Authentication/3rd Party/ParseApple.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,13 @@ public struct ParseApple<AuthenticatedUser: ParseUser>: 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.
Expand Down Expand Up @@ -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<AuthenticatedUser, ParseError>) -> 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]?,
Expand Down Expand Up @@ -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<AuthenticatedUser, ParseError> {
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, *)
Expand Down Expand Up @@ -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<AuthenticatedUser, ParseError>) -> 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]?,
Expand Down Expand Up @@ -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<AuthenticatedUser, ParseError> {
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)
}

Expand Down
23 changes: 19 additions & 4 deletions Tests/ParseSwiftTests/ParseAppleCombineTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -201,9 +211,14 @@ class ParseAppleCombineTests: XCTestCase { // swiftlint:disable:this type_body_l
_ = try loginNormally()
MockURLProtocol.removeAll()

let authData = ParseApple<User>
guard let tokenData = "this".data(using: .utf8) else {
XCTFail("Couldn't convert token data to string")
return
}

let authData = try ParseApple<User>
.AuthenticationKeys.id.makeDictionary(user: "testing",
identityToken: "this")
identityToken: tokenData)
User.current?.authData = [User.apple.__type: authData]
XCTAssertTrue(User.apple.isLinked)

Expand Down
52 changes: 39 additions & 13 deletions Tests/ParseSwiftTests/ParseAppleTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,23 @@ class ParseAppleTests: XCTestCase {
}

func testAuthenticationKeys() throws {
let authData = ParseApple<User>
let tokenData = Data([0, 1, 127, 128, 255])
let authData = try ParseApple<User>
.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<User>
guard let tokenData = "this".data(using: .utf8) else {
XCTFail("Couldn't convert token data to string")
return
}

let authData = try ParseApple<User>
.AuthenticationKeys.id.makeDictionary(user: "testing",
identityToken: "this")
identityToken: tokenData)
serverResponse.username = "hello"
serverResponse.password = "world"
serverResponse.objectId = "yarr"
Expand All @@ -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):
Expand Down Expand Up @@ -190,9 +196,14 @@ class ParseAppleTests: XCTestCase {
func testReplaceAnonymousWithApple() throws {
try loginAnonymousUser()
MockURLProtocol.removeAll()
let authData = ParseApple<User>
guard let tokenData = "this".data(using: .utf8) else {
XCTFail("Couldn't convert token data to string")
return
}

let authData = try ParseApple<User>
.AuthenticationKeys.id.makeDictionary(user: "testing",
identityToken: "this")
identityToken: tokenData)

var serverResponse = LoginSignupResponse()
serverResponse.username = "hello"
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand All @@ -324,9 +345,14 @@ class ParseAppleTests: XCTestCase {
func testUnlink() throws {
_ = try loginNormally()
MockURLProtocol.removeAll()
let authData = ParseApple<User>
guard let tokenData = "this".data(using: .utf8) else {
XCTFail("Couldn't convert token data to string")
return
}

let authData = try ParseApple<User>
.AuthenticationKeys.id.makeDictionary(user: "testing",
identityToken: "this")
identityToken: tokenData)
User.current?.authData = [User.apple.__type: authData]
XCTAssertTrue(User.apple.isLinked)

Expand Down