Skip to content

Commit

Permalink
Recreate new installation after deletion from keychain (#112)
Browse files Browse the repository at this point in the history
* Create new installation automatically after it's removed from keychain

* Add changelog

* Make sure installationId's aren't nil
  • Loading branch information
cbaker6 authored Apr 2, 2021
1 parent 7024222 commit 3852a93
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 51 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.2.5...1.2.6)

__Fixes__
- Crash when linking auth types due to server not sending sessionToken ([#109](https://github.com/parse-community/Parse-Swift/pull/109)), thanks to [Corey Baker](https://github.com/cbaker6).
- Recreate installation automatically after deletion from Keychain ([#112](https://github.com/parse-community/Parse-Swift/pull/112)), thanks to [Corey Baker](https://github.com/cbaker6).
- Error when linking auth types due to server not sending sessionToken ([#109](https://github.com/parse-community/Parse-Swift/pull/109)), thanks to [Corey Baker](https://github.com/cbaker6).

### 1.2.5
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.2.4...1.2.5)
Expand Down
4 changes: 4 additions & 0 deletions Sources/ParseSwift/Objects/ParseInstallation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ extension ParseInstallation {
#if !os(Linux) && !os(Android)
try? KeychainStore.shared.delete(valueFor: ParseStorage.Keys.currentInstallation)
#endif
//Prepare new installation
DispatchQueue.main.async {
_ = BaseParseInstallation()
}
}

/**
Expand Down
59 changes: 37 additions & 22 deletions Tests/ParseSwiftTests/ParseUserCombineTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -293,32 +293,47 @@ class ParseUserCombineTests: XCTestCase { // swiftlint:disable:this type_body_le
}

let expectation1 = XCTestExpectation(description: "Logout user1")
let publisher = User.logoutPublisher()
.sink(receiveCompletion: { result in

if case let .failure(error) = result {
XCTFail(error.localizedDescription)
}
DispatchQueue.main.async {
guard let oldInstallationId = BaseParseInstallation.current?.installationId else {
XCTFail("Should have unwrapped")
expectation1.fulfill()

}, receiveValue: { _ in
if let userFromKeychain = BaseParseUser.current {
XCTFail("\(userFromKeychain) wasn't deleted from Keychain during logout")
return
}
let publisher = User.logoutPublisher()
.sink(receiveCompletion: { result in

if let installationFromMemory: CurrentInstallationContainer<BaseParseInstallation>
= try? ParseStorage.shared.get(valueFor: ParseStorage.Keys.currentInstallation) {
XCTFail("\(installationFromMemory) wasn't deleted from memory during logout")
}
if case let .failure(error) = result {
XCTFail(error.localizedDescription)
}
expectation1.fulfill()

#if !os(Linux) && !os(Android)
if let installationFromKeychain: CurrentInstallationContainer<BaseParseInstallation>
= try? KeychainStore.shared.get(valueFor: ParseStorage.Keys.currentInstallation) {
XCTFail("\(installationFromKeychain) wasn't deleted from Keychain during logout")
}
#endif
})
publisher.store(in: &subscriptions)
}, receiveValue: { _ in
if let userFromKeychain = BaseParseUser.current {
XCTFail("\(userFromKeychain) wasn't deleted from Keychain during logout")
}
DispatchQueue.main.async {
if let installationFromMemory: CurrentInstallationContainer<BaseParseInstallation>
= try? ParseStorage.shared.get(valueFor: ParseStorage.Keys.currentInstallation) {
if installationFromMemory.installationId == oldInstallationId
&& installationFromMemory.installationId != nil {
XCTFail("\(installationFromMemory) wasn't deleted and recreated in memory during logout")
}
}

#if !os(Linux) && !os(Android)
if let installationFromKeychain: CurrentInstallationContainer<BaseParseInstallation>
= try? KeychainStore.shared.get(valueFor: ParseStorage.Keys.currentInstallation) {
if installationFromKeychain.installationId == oldInstallationId
&& installationFromKeychain.installationId != nil {
// swiftlint:disable:next line_length
XCTFail("\(installationFromKeychain) wasn't deleted and recreated in Keychain during logout")
}
}
#endif
}
})
publisher.store(in: &subscriptions)
}
wait(for: [expectation1], timeout: 20.0)
}

Expand Down
85 changes: 57 additions & 28 deletions Tests/ParseSwiftTests/ParseUserTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1094,48 +1094,77 @@ class ParseUserTests: XCTestCase { // swiftlint:disable:this type_body_length
return nil
}
}
do {
try User.logout()
if let userFromKeychain = BaseParseUser.current {
XCTFail("\(userFromKeychain) wasn't deleted from Keychain during logout")
}

if let installationFromKeychain = BaseParseInstallation.current {
XCTFail("\(installationFromKeychain) wasn't deleted from Keychain during logout")
DispatchQueue.main.async {
guard let oldInstallationId = BaseParseInstallation.current?.installationId else {
XCTFail("Should have unwrapped")
return
}
do {
try User.logout()
if let userFromKeychain = BaseParseUser.current {
XCTFail("\(userFromKeychain) wasn't deleted from Keychain during logout")
}
DispatchQueue.main.async {
if let installationFromKeychain = BaseParseInstallation.current {
if installationFromKeychain.installationId == oldInstallationId
&& installationFromKeychain.installationId != nil {
XCTFail("\(installationFromKeychain) wasn't deleted then created in Keychain during logout")
}
}
}
} catch {
XCTFail(error.localizedDescription)
}
} catch {
XCTFail(error.localizedDescription)
}
}

func logoutAsync(callbackQueue: DispatchQueue) {

let expectation1 = XCTestExpectation(description: "Logout user1")
User.logout(callbackQueue: callbackQueue) { result in

switch result {
DispatchQueue.main.async {
guard let oldInstallationId = BaseParseInstallation.current?.installationId else {
XCTFail("Should have unwrapped")
expectation1.fulfill()
return
}

case .success:
if let userFromKeychain = BaseParseUser.current {
XCTFail("\(userFromKeychain) wasn't deleted from Keychain during logout")
}
User.logout(callbackQueue: callbackQueue) { result in

if let installationFromMemory: CurrentInstallationContainer<BaseParseInstallation>
= try? ParseStorage.shared.get(valueFor: ParseStorage.Keys.currentInstallation) {
XCTFail("\(installationFromMemory) wasn't deleted from memory during logout")
}
switch result {

#if !os(Linux) && !os(Android)
if let installationFromKeychain: CurrentInstallationContainer<BaseParseInstallation>
= try? KeychainStore.shared.get(valueFor: ParseStorage.Keys.currentInstallation) {
XCTFail("\(installationFromKeychain) wasn't deleted from Keychain during logout")
}
#endif
case .success:
if let userFromKeychain = BaseParseUser.current {
XCTFail("\(userFromKeychain) wasn't deleted from Keychain during logout")
}
DispatchQueue.main.async {
if let installationFromMemory: CurrentInstallationContainer<BaseParseInstallation>
= try? ParseStorage.shared.get(valueFor: ParseStorage.Keys.currentInstallation) {
if installationFromMemory.installationId == oldInstallationId
&& installationFromMemory.installationId != nil {
// swiftlint:disable:next line_length
XCTFail("\(installationFromMemory) wasn't deleted and recreated in memory during logout")
}
}

case .failure(let error):
XCTFail(error.localizedDescription)
#if !os(Linux) && !os(Android)
if let installationFromKeychain: CurrentInstallationContainer<BaseParseInstallation>
= try? KeychainStore.shared.get(valueFor: ParseStorage.Keys.currentInstallation) {
if installationFromKeychain.installationId == oldInstallationId
&& installationFromKeychain.installationId != nil {
// swiftlint:disable:next line_length
XCTFail("\(installationFromKeychain) wasn't deleted and recreated in Keychain during logout")
}
}
#endif
}

case .failure(let error):
XCTFail(error.localizedDescription)
}
expectation1.fulfill()
}
expectation1.fulfill()
}
wait(for: [expectation1], timeout: 20.0)
}
Expand Down

0 comments on commit 3852a93

Please sign in to comment.