mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-25 09:41:00 +00:00
Revoke access token when removing account
This commit is contained in:
parent
4bcb862065
commit
fb7d23b5d6
7 changed files with 68 additions and 15 deletions
|
@ -44,6 +44,8 @@
|
|||
D019E6EE24DF7BF300697C7D /* IdentityDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D019E6EC24DF7BF300697C7D /* IdentityDatabase.swift */; };
|
||||
D019E6F024DF7C2F00697C7D /* DatabaseError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D019E6EF24DF7C2F00697C7D /* DatabaseError.swift */; };
|
||||
D019E6F124DF7C2F00697C7D /* DatabaseError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D019E6EF24DF7C2F00697C7D /* DatabaseError.swift */; };
|
||||
D03DF45B24E62A68007A8CD5 /* DeletionEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03DF45A24E62A68007A8CD5 /* DeletionEndpoint.swift */; };
|
||||
D03DF45C24E62A68007A8CD5 /* DeletionEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03DF45A24E62A68007A8CD5 /* DeletionEndpoint.swift */; };
|
||||
D047FAAE24C3E21200AF17C5 /* MetatextApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D047FA8524C3E21000AF17C5 /* MetatextApp.swift */; };
|
||||
D047FAAF24C3E21200AF17C5 /* MetatextApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D047FA8524C3E21000AF17C5 /* MetatextApp.swift */; };
|
||||
D047FAB224C3E21200AF17C5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D047FA8724C3E21200AF17C5 /* Assets.xcassets */; };
|
||||
|
@ -238,6 +240,7 @@
|
|||
D019E6E024DF72E700697C7D /* InstanceEndpoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InstanceEndpoint.swift; sourceTree = "<group>"; };
|
||||
D019E6EC24DF7BF300697C7D /* IdentityDatabase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IdentityDatabase.swift; sourceTree = "<group>"; };
|
||||
D019E6EF24DF7C2F00697C7D /* DatabaseError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DatabaseError.swift; sourceTree = "<group>"; };
|
||||
D03DF45A24E62A68007A8CD5 /* DeletionEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletionEndpoint.swift; sourceTree = "<group>"; };
|
||||
D047FA8524C3E21000AF17C5 /* MetatextApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetatextApp.swift; sourceTree = "<group>"; };
|
||||
D047FA8724C3E21200AF17C5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
D047FA8C24C3E21200AF17C5 /* Metatext.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Metatext.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -396,6 +399,7 @@
|
|||
D019E6DF24DF72E700697C7D /* AccessTokenEndpoint.swift */,
|
||||
D019E6DE24DF72E700697C7D /* AccountEndpoint.swift */,
|
||||
D019E6DC24DF72E700697C7D /* AppAuthorizationEndpoint.swift */,
|
||||
D03DF45A24E62A68007A8CD5 /* DeletionEndpoint.swift */,
|
||||
D019E6E024DF72E700697C7D /* InstanceEndpoint.swift */,
|
||||
D019E6DD24DF72E700697C7D /* PreferencesEndpoint.swift */,
|
||||
D0EC8DED24E2704D00A08489 /* PushSubscriptionEndpoint.swift */,
|
||||
|
@ -934,6 +938,7 @@
|
|||
D0091B6E24DD68090040E8D2 /* PreferencesView.swift in Sources */,
|
||||
D0159F8F24DE743700E78478 /* IdentitiesView.swift in Sources */,
|
||||
D0EC8DEB24E26F1100A08489 /* PushSubscription.swift in Sources */,
|
||||
D03DF45B24E62A68007A8CD5 /* DeletionEndpoint.swift in Sources */,
|
||||
D0DB6EF424C5228A00D965FE /* AddIdentityView.swift in Sources */,
|
||||
D074577724D29006004758DB /* MockWebAuthSession.swift in Sources */,
|
||||
D0159FA524DE989700E78478 /* NSMutableAttributedString+Extensions.swift in Sources */,
|
||||
|
@ -1020,6 +1025,7 @@
|
|||
D074577B24D29366004758DB /* URLSessionConfiguration+Extensions.swift in Sources */,
|
||||
D0ED1BB824CE47F400B4899C /* WebAuthSession.swift in Sources */,
|
||||
D0EC8DEC24E26F1100A08489 /* PushSubscription.swift in Sources */,
|
||||
D03DF45C24E62A68007A8CD5 /* DeletionEndpoint.swift in Sources */,
|
||||
D0A1CA7524DAC2F1003063E9 /* KingfisherOptionsInfo+Extensions.swift in Sources */,
|
||||
D0ED1BC524CED54D00B4899C /* HTTPTarget.swift in Sources */,
|
||||
D0C963FF24CC3812003BD330 /* Publisher+Extensions.swift in Sources */,
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
enum DeletionEndpoint {
|
||||
case oauthRevoke(token: String, clientID: String, clientSecret: String)
|
||||
}
|
||||
|
||||
extension DeletionEndpoint: MastodonEndpoint {
|
||||
typealias ResultType = [String: String]
|
||||
|
||||
var context: [String] {
|
||||
switch self {
|
||||
case .oauthRevoke:
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
var pathComponentsInContext: [String] {
|
||||
switch self {
|
||||
case .oauthRevoke:
|
||||
return ["oauth", "revoke"]
|
||||
}
|
||||
}
|
||||
|
||||
var method: HTTPMethod {
|
||||
switch self {
|
||||
case .oauthRevoke:
|
||||
return .post
|
||||
}
|
||||
}
|
||||
|
||||
var parameters: [String: Any]? {
|
||||
switch self {
|
||||
case let .oauthRevoke(token, clientID, clientSecret):
|
||||
return ["token": token, "client_id": clientID, "client_secret": clientSecret]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -50,18 +50,22 @@ extension IdentitiesService {
|
|||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func deleteIdentity(id: UUID) -> AnyPublisher<Void, Error> {
|
||||
let environment = self.environment
|
||||
func deleteIdentity(_ identity: Identity) -> AnyPublisher<Void, Error> {
|
||||
let secretsService = SecretsService(identityID: identity.id, keychainService: environment.keychainServiceType)
|
||||
let networkClient = MastodonClient(session: environment.session)
|
||||
|
||||
return identityDatabase.deleteIdentity(id: id)
|
||||
.tryMap { _ -> Void in
|
||||
try SecretsService(
|
||||
identityID: id,
|
||||
keychainService: environment.keychainServiceType)
|
||||
.deleteAllItems()
|
||||
networkClient.instanceURL = identity.url
|
||||
|
||||
return ()
|
||||
return identityDatabase.deleteIdentity(id: identity.id)
|
||||
.tryMap {
|
||||
DeletionEndpoint.oauthRevoke(
|
||||
token: try secretsService.item(.accessToken),
|
||||
clientID: try secretsService.item(.clientID),
|
||||
clientSecret: try secretsService.item(.clientSecret))
|
||||
}
|
||||
.flatMap(networkClient.request)
|
||||
.tryMap { _ in try secretsService.deleteAllItems() }
|
||||
.print()
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ class IdentityService {
|
|||
keychainService: environment.keychainServiceType)
|
||||
networkClient = MastodonClient(session: environment.session)
|
||||
networkClient.instanceURL = identity.url
|
||||
networkClient.accessToken = try secretsService.item(.accessToken)
|
||||
networkClient.accessToken = try? secretsService.item(.accessToken)
|
||||
|
||||
observation.catch { [weak self] error -> Empty<Identity, Never> in
|
||||
self?.observationErrorsInput.send(error)
|
||||
|
|
|
@ -31,6 +31,10 @@ extension SecretsService {
|
|||
}
|
||||
}
|
||||
|
||||
enum SecretsServiceError: Error {
|
||||
case itemAbsent
|
||||
}
|
||||
|
||||
extension SecretsService.Item {
|
||||
enum Kind {
|
||||
case genericPassword
|
||||
|
@ -53,11 +57,11 @@ extension SecretsService {
|
|||
service: Self.keychainServiceName)
|
||||
}
|
||||
|
||||
func item<T: SecretsStorable>(_ item: Item) throws -> T? {
|
||||
func item<T: SecretsStorable>(_ item: Item) throws -> T {
|
||||
guard let data = try keychainService.getGenericPassword(
|
||||
account: key(item: item),
|
||||
service: Self.keychainServiceName) else {
|
||||
return nil
|
||||
throw SecretsServiceError.itemAbsent
|
||||
}
|
||||
|
||||
return try T.fromDataStoredInSecrets(data)
|
||||
|
|
|
@ -70,8 +70,8 @@ extension RootViewModel {
|
|||
mainNavigationViewModel = MainNavigationViewModel(identityService: identityService)
|
||||
}
|
||||
|
||||
func deleteIdentity(id: UUID) {
|
||||
identitiesService.deleteIdentity(id: id)
|
||||
func deleteIdentity(_ identity: Identity) {
|
||||
identitiesService.deleteIdentity(identity)
|
||||
.sink { _ in } receiveValue: { _ in }
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ struct IdentitiesView: View {
|
|||
.onDelete {
|
||||
guard let index = $0.first else { return }
|
||||
|
||||
rootViewModel.deleteIdentity(id: viewModel.identities[index].id)
|
||||
rootViewModel.deleteIdentity(viewModel.identities[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue