From 0e1cbce10d2d777e556d4d89cf190a527db572db Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Fri, 27 Jan 2023 18:42:11 -0500 Subject: [PATCH] Revoke token and destroy stores when logging out --- .../Pachyderm/Sources/Pachyderm/Client.swift | 21 +++++++++++ Tusker.xcodeproj/project.pbxproj | 4 +++ Tusker/API/LogoutService.swift | 35 +++++++++++++++++++ Tusker/API/MastodonController.swift | 4 +++ Tusker/Scenes/MainSceneDelegate.swift | 2 +- .../PreferencesNavigationController.swift | 2 +- .../Screens/Preferences/PreferencesView.swift | 2 +- 7 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 Tusker/API/LogoutService.swift diff --git a/Packages/Pachyderm/Sources/Pachyderm/Client.swift b/Packages/Pachyderm/Sources/Pachyderm/Client.swift index eb16d6a5..b7a0a932 100644 --- a/Packages/Pachyderm/Sources/Pachyderm/Client.swift +++ b/Packages/Pachyderm/Sources/Pachyderm/Client.swift @@ -155,6 +155,27 @@ public class Client { } } + public func revokeAccessToken() async throws { + guard let accessToken else { + return + } + let request = Request(method: .post, path: "/oauth/revoke", body: ParametersBody([ + "token" => accessToken, + "client_id" => clientID!, + "client_secret" => clientSecret!, + ])) + return try await withCheckedThrowingContinuation({ continuation in + self.run(request) { response in + switch response { + case .failure(let error): + continuation.resume(throwing: error) + case .success(_, _): + continuation.resume() + } + } + }) + } + public func nodeInfo(completion: @escaping Callback) { let wellKnown = Request(method: .get, path: "/.well-known/nodeinfo") run(wellKnown) { result in diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj index 1b5680f3..02253574 100644 --- a/Tusker.xcodeproj/project.pbxproj +++ b/Tusker.xcodeproj/project.pbxproj @@ -326,6 +326,7 @@ D6DD2A45273D6C5700386A6C /* GIFImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD2A44273D6C5700386A6C /* GIFImageView.swift */; }; D6DD353D22F28CD000A9563A /* ContentWarningCopyMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD353C22F28CD000A9563A /* ContentWarningCopyMode.swift */; }; D6DD353F22F502EC00A9563A /* Preferences+Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD353E22F502EC00A9563A /* Preferences+Notification.swift */; }; + D6DD8FFD298495A8002AD3FD /* LogoutService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD8FFC298495A8002AD3FD /* LogoutService.swift */; }; D6DF95C12533F5DE0027A9B6 /* RelationshipMO.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DF95C02533F5DE0027A9B6 /* RelationshipMO.swift */; }; D6DFC69E242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DFC69D242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift */; }; D6DFC6A0242C4CCC00ACC392 /* Weak.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DFC69F242C4CCC00ACC392 /* Weak.swift */; }; @@ -738,6 +739,7 @@ D6DD2A44273D6C5700386A6C /* GIFImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GIFImageView.swift; sourceTree = ""; }; D6DD353C22F28CD000A9563A /* ContentWarningCopyMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentWarningCopyMode.swift; sourceTree = ""; }; D6DD353E22F502EC00A9563A /* Preferences+Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Preferences+Notification.swift"; sourceTree = ""; }; + D6DD8FFC298495A8002AD3FD /* LogoutService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogoutService.swift; sourceTree = ""; }; D6DF95C02533F5DE0027A9B6 /* RelationshipMO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelationshipMO.swift; sourceTree = ""; }; D6DFC69D242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackpadScrollGestureRecognizer.swift; sourceTree = ""; }; D6DFC69F242C4CCC00ACC392 /* Weak.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Weak.swift; sourceTree = ""; }; @@ -1664,6 +1666,7 @@ D61F75B4293BD97400C0B37F /* DeleteFilterService.swift */, D65B4B6129771A3F00DABDFB /* FetchStatusService.swift */, D65B4B6529773AE600DABDFB /* DeleteStatusService.swift */, + D6DD8FFC298495A8002AD3FD /* LogoutService.swift */, ); path = API; sourceTree = ""; @@ -1941,6 +1944,7 @@ D6093FB725BE0CF3004811E6 /* TrendHistoryView.swift in Sources */, D6EBF01723C55E0D00AE061B /* UISceneSession+MastodonController.swift in Sources */, D61F759229365C6C00C0B37F /* CollectionViewController.swift in Sources */, + D6DD8FFD298495A8002AD3FD /* LogoutService.swift in Sources */, 04DACE8C212CB14B009840C4 /* MainTabBarViewController.swift in Sources */, D68E525D24A3E8F00054355A /* SearchViewController.swift in Sources */, D61F75BB293C183100C0B37F /* HTMLConverter.swift in Sources */, diff --git a/Tusker/API/LogoutService.swift b/Tusker/API/LogoutService.swift new file mode 100644 index 00000000..42b76255 --- /dev/null +++ b/Tusker/API/LogoutService.swift @@ -0,0 +1,35 @@ +// +// LogoutService.swift +// Tusker +// +// Created by Shadowfacts on 1/27/23. +// Copyright © 2023 Shadowfacts. All rights reserved. +// + +import Foundation + +@MainActor +class LogoutService { + let accountInfo: LocalData.UserAccountInfo + private let mastodonController: MastodonController + + init(accountInfo: LocalData.UserAccountInfo) { + self.accountInfo = accountInfo + self.mastodonController = MastodonController.getForAccount(accountInfo) + } + + func run() { + Task.detached { + try? await self.mastodonController.client.revokeAccessToken() + } + MastodonController.removeForAccount(accountInfo) + LocalData.shared.removeAccount(accountInfo) + let psc = mastodonController.persistentContainer.persistentStoreCoordinator + for store in psc.persistentStores { + guard let url = store.url else { + continue + } + try? psc.destroyPersistentStore(at: url, type: .sqlite) + } + } +} diff --git a/Tusker/API/MastodonController.swift b/Tusker/API/MastodonController.swift index 3a1cfb69..d25c9616 100644 --- a/Tusker/API/MastodonController.swift +++ b/Tusker/API/MastodonController.swift @@ -31,6 +31,10 @@ class MastodonController: ObservableObject { } } + static func removeForAccount(_ account: LocalData.UserAccountInfo) { + all.removeValue(forKey: account) + } + static func resetAll() { all = [:] } diff --git a/Tusker/Scenes/MainSceneDelegate.swift b/Tusker/Scenes/MainSceneDelegate.swift index 34a4ec0f..43c1a731 100644 --- a/Tusker/Scenes/MainSceneDelegate.swift +++ b/Tusker/Scenes/MainSceneDelegate.swift @@ -214,7 +214,7 @@ class MainSceneDelegate: UIResponder, UIWindowSceneDelegate, TuskerSceneDelegate guard let account = window?.windowScene?.session.mastodonController?.accountInfo else { return } - LocalData.shared.removeAccount(account) + LogoutService(accountInfo: account).run() if LocalData.shared.onboardingComplete { activateAccount(LocalData.shared.accounts.first!, animated: false) } else { diff --git a/Tusker/Screens/Preferences/PreferencesNavigationController.swift b/Tusker/Screens/Preferences/PreferencesNavigationController.swift index 78d78b3e..5514a635 100644 --- a/Tusker/Screens/Preferences/PreferencesNavigationController.swift +++ b/Tusker/Screens/Preferences/PreferencesNavigationController.swift @@ -85,7 +85,7 @@ class PreferencesNavigationController: UINavigationController { sceneDelegate.logoutCurrent() } } else { - LocalData.shared.removeAccount(LocalData.shared.getMostRecentAccount()!) + LogoutService(accountInfo: LocalData.shared.getMostRecentAccount()!).run() let accountID = LocalData.shared.getMostRecentAccount()?.id UIApplication.shared.requestSceneSessionActivation(nil, userActivity: UserActivityManager.mainSceneActivity(accountID: accountID), options: nil) UIApplication.shared.requestSceneSessionDestruction(windowScene.session, options: nil) diff --git a/Tusker/Screens/Preferences/PreferencesView.swift b/Tusker/Screens/Preferences/PreferencesView.swift index fc40a070..de97071d 100644 --- a/Tusker/Screens/Preferences/PreferencesView.swift +++ b/Tusker/Screens/Preferences/PreferencesView.swift @@ -54,7 +54,7 @@ struct PreferencesView: View { indices.remove(index) } - indices.forEach { localData.removeAccount(localData.accounts[$0]) } + indices.forEach { LogoutService(accountInfo: localData.accounts[$0]).run() } if logoutFromCurrent { self.logoutPressed()