forked from StanfordSpezi/SpeziAccount
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce the AccountNotifyStandard (StanfordSpezi#24)
# Introduce the AccountNotifyStandard ## ♻️ Current situation & Problem Currently, there is no way for an App to distinguish between Account logout and removal. This is especially important if the App associates other data (questionnaires, additional user information) with the user account that must be deleted as well. This PR adds the `AccountNotifyStandard` constraint that allows to get notified about an account removal. ## ⚙️ Release Notes * Add `AccountNotifyStandard` ## 📚 Documentation Documentation was added and updated. ## ✅ Testing Tests were added to verify functionality. ## 📝 Code of Conduct & Contributing Guidelines By submitting creating this pull request, you agree to follow our [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md): - [x] I agree to follow the [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md).
- Loading branch information
Showing
11 changed files
with
212 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// | ||
// This source file is part of the Stanford Spezi open-source project | ||
// | ||
// SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
|
||
import Spezi | ||
|
||
|
||
/// A `Spezi` Standard that allows to react to certain Account-based events. | ||
public protocol AccountNotifyStandard: Standard { | ||
/// Notifies the Standard that the associated account was requested to be deleted by the user. | ||
/// | ||
/// Use this method to cleanup any account related data that might be associated with the account. | ||
func deletedAccount() async throws | ||
} |
44 changes: 44 additions & 0 deletions
44
Sources/SpeziAccount/AccountService/Wrapper/NotifyStandardBackedAccountService.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// | ||
// This source file is part of the Stanford Spezi open-source project | ||
// | ||
// SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
|
||
import Spezi | ||
|
||
|
||
actor NotifyStandardBackedAccountService<Service: AccountService, Standard: AccountNotifyStandard>: AccountService, StandardBacked { | ||
@AccountReference private var account | ||
|
||
let accountService: Service | ||
let standard: Standard | ||
|
||
nonisolated var configuration: AccountServiceConfiguration { | ||
accountService.configuration | ||
} | ||
|
||
nonisolated var viewStyle: Service.ViewStyle { | ||
accountService.viewStyle | ||
} | ||
|
||
|
||
init(service accountService: Service, standard: Standard) { | ||
self.accountService = accountService | ||
self.standard = standard | ||
} | ||
|
||
|
||
func delete() async throws { | ||
try await standard.deletedAccount() | ||
try await accountService.delete() | ||
} | ||
} | ||
|
||
|
||
extension NotifyStandardBackedAccountService: EmbeddableAccountService where Service: EmbeddableAccountService {} | ||
|
||
extension NotifyStandardBackedAccountService: UserIdPasswordAccountService where Service: UserIdPasswordAccountService {} | ||
|
||
extension NotifyStandardBackedAccountService: IdentityProvider where Service: IdentityProvider {} |
97 changes: 97 additions & 0 deletions
97
Sources/SpeziAccount/AccountService/Wrapper/StandardBacked.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// | ||
// This source file is part of the Stanford Spezi open-source project | ||
// | ||
// SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
|
||
import Spezi | ||
|
||
|
||
/// Internal marker protocol to determine what ``AccountService`` require assistance by a ``AccountStorageStandard``. | ||
protocol StandardBacked: AccountService { | ||
associatedtype Service: AccountService | ||
associatedtype AccountStandard: Standard | ||
|
||
var accountService: Service { get } | ||
var standard: AccountStandard { get } | ||
|
||
init(service: Service, standard: AccountStandard) | ||
|
||
func isBacking(service accountService: any AccountService) -> Bool | ||
} | ||
|
||
|
||
extension StandardBacked { | ||
var backedId: String { | ||
if let nestedBacked = accountService as? any StandardBacked { | ||
return nestedBacked.backedId | ||
} | ||
|
||
return accountService.id | ||
} | ||
|
||
|
||
func isBacking(service: any AccountService) -> Bool { | ||
if let nestedBacked = self.accountService as? any StandardBacked { | ||
return nestedBacked.isBacking(service: service) | ||
} | ||
return self.accountService.objId == service.objId | ||
} | ||
} | ||
|
||
|
||
extension StandardBacked { | ||
func signUp(signupDetails: SignupDetails) async throws { | ||
try await accountService.signUp(signupDetails: signupDetails) | ||
} | ||
|
||
func logout() async throws { | ||
try await accountService.logout() | ||
} | ||
|
||
func delete() async throws { | ||
try await accountService.delete() | ||
} | ||
|
||
func updateAccountDetails(_ modifications: AccountModifications) async throws { | ||
try await accountService.updateAccountDetails(modifications) | ||
} | ||
} | ||
|
||
|
||
extension StandardBacked where Self: UserIdPasswordAccountService, Service: UserIdPasswordAccountService { | ||
func login(userId: String, password: String) async throws { | ||
try await accountService.login(userId: userId, password: password) | ||
} | ||
|
||
func resetPassword(userId: String) async throws { | ||
try await accountService.resetPassword(userId: userId) | ||
} | ||
} | ||
|
||
|
||
extension AccountService { | ||
func backedBy(standard: any AccountStorageStandard) -> any AccountService { | ||
standard.backedService(with: self) | ||
} | ||
|
||
func backedBy(standard: any AccountNotifyStandard) -> any AccountService { | ||
standard.backedService(with: self) | ||
} | ||
} | ||
|
||
|
||
extension AccountStorageStandard { | ||
fileprivate nonisolated func backedService<Service: AccountService>(with service: Service) -> any AccountService { | ||
StorageStandardBackedAccountService(service: service, standard: self) | ||
} | ||
} | ||
|
||
|
||
extension AccountNotifyStandard { | ||
fileprivate nonisolated func backedService<Service: AccountService>(with service: Service) -> any AccountService { | ||
NotifyStandardBackedAccountService(service: service, standard: self) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -87,7 +87,9 @@ final class AccountOverviewTests: XCTestCase { | |
|
||
sleep(2) | ||
app.verify() | ||
|
||
XCTAssertFalse(app.staticTexts["[email protected]"].waitForExistence(timeout: 0.5)) | ||
XCTAssertTrue(app.staticTexts["Got notified about deletion!"].waitForExistence(timeout: 2.0)) | ||
} | ||
|
||
func testEditDiscard() { | ||
|
Oops, something went wrong.