Skip to content

Commit

Permalink
Adding Deletion of APNS Tokens on logout
Browse files Browse the repository at this point in the history
  • Loading branch information
stigi committed Apr 24, 2024
1 parent 7898d54 commit 02c1723
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 7 deletions.
12 changes: 12 additions & 0 deletions MagicBell.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@
9415C47B2BD932D30099C470 /* APNSTokenNetworkDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9415C46A2BD932D30099C470 /* APNSTokenNetworkDataSource.swift */; };
9415C47C2BD932D30099C470 /* RegisterAPNSTokensInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9415C46C2BD932D30099C470 /* RegisterAPNSTokensInteractor.swift */; };
9415C47D2BD932D30099C470 /* RegisterAPNSTokensInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9415C46C2BD932D30099C470 /* RegisterAPNSTokensInteractor.swift */; };
9415C4812BD933A50099C470 /* DeleteAPNSTokenQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9415C4802BD933A50099C470 /* DeleteAPNSTokenQuery.swift */; };
9415C4822BD933A50099C470 /* DeleteAPNSTokenQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9415C4802BD933A50099C470 /* DeleteAPNSTokenQuery.swift */; };
9415C4842BD933AA0099C470 /* DeleteAPNSTokenInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9415C4832BD933AA0099C470 /* DeleteAPNSTokenInteractor.swift */; };
9415C4852BD933AA0099C470 /* DeleteAPNSTokenInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9415C4832BD933AA0099C470 /* DeleteAPNSTokenInteractor.swift */; };
94CC7AC32BBDE8E800F4AFE7 /* NotificationPreferencesEntityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94CC7AC22BBDE8E800F4AFE7 /* NotificationPreferencesEntityTests.swift */; };
D27CF1BA27906FDD00897BCB /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CF1B927906FDD00897BCB /* User.swift */; };
D280727B27A2F1C000FD941A /* Nimble.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = D280727A27A2F1C000FD941A /* Nimble.xcframework */; };
Expand Down Expand Up @@ -335,6 +339,8 @@
9415C4692BD932D30099C470 /* RegisterAPNSTokenQuery.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegisterAPNSTokenQuery.swift; sourceTree = "<group>"; };
9415C46A2BD932D30099C470 /* APNSTokenNetworkDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APNSTokenNetworkDataSource.swift; sourceTree = "<group>"; };
9415C46C2BD932D30099C470 /* RegisterAPNSTokensInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegisterAPNSTokensInteractor.swift; sourceTree = "<group>"; };
9415C4802BD933A50099C470 /* DeleteAPNSTokenQuery.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeleteAPNSTokenQuery.swift; sourceTree = "<group>"; };
9415C4832BD933AA0099C470 /* DeleteAPNSTokenInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeleteAPNSTokenInteractor.swift; sourceTree = "<group>"; };
94CC7AC22BBDE8E800F4AFE7 /* NotificationPreferencesEntityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPreferencesEntityTests.swift; sourceTree = "<group>"; };
D27CF1B927906FDD00897BCB /* User.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; };
D280727827A2E40C00FD941A /* MagicBell.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = MagicBell.podspec; sourceTree = "<group>"; };
Expand Down Expand Up @@ -844,6 +850,7 @@
9415C4672BD932D30099C470 /* Data */ = {
isa = PBXGroup;
children = (
9415C4802BD933A50099C470 /* DeleteAPNSTokenQuery.swift */,
9415C4692BD932D30099C470 /* RegisterAPNSTokenQuery.swift */,
9415C46A2BD932D30099C470 /* APNSTokenNetworkDataSource.swift */,
);
Expand All @@ -853,6 +860,7 @@
9415C46B2BD932D30099C470 /* Interactor */ = {
isa = PBXGroup;
children = (
9415C4832BD933AA0099C470 /* DeleteAPNSTokenInteractor.swift */,
9415C46C2BD932D30099C470 /* RegisterAPNSTokensInteractor.swift */,
);
path = Interactor;
Expand Down Expand Up @@ -1045,6 +1053,7 @@
59B2DDAE276B5C4C0038B0EA /* CodingKey+JSON.swift in Sources */,
59C3CDC0274D2CC20043BA77 /* GetConfigInteractor.swift in Sources */,
D2D277262747C9CF00B5F69E /* ActionNotificationNetworkDataSource.swift in Sources */,
9415C4812BD933A50099C470 /* DeleteAPNSTokenQuery.swift in Sources */,
59C3CDC4274D36360043BA77 /* DeleteConfigInteractor.swift in Sources */,
59799E5C2746609A00BFB375 /* NotificationNetworkDataSource.swift in Sources */,
59C12ECF2746DC7100311D24 /* PushSubscription.swift in Sources */,
Expand Down Expand Up @@ -1100,6 +1109,7 @@
59C3CDBC274D039D0043BA77 /* MagicBellError.swift in Sources */,
59799E312746587000BFB375 /* MagicBellClient.swift in Sources */,
59799E38274659D800BFB375 /* Environment.swift in Sources */,
9415C4842BD933AA0099C470 /* DeleteAPNSTokenInteractor.swift in Sources */,
D27CF1BA27906FDD00897BCB /* User.swift in Sources */,
59C3CDC2274D2F220043BA77 /* EncodableToDataMapper.swift in Sources */,
9415C47C2BD932D30099C470 /* RegisterAPNSTokensInteractor.swift in Sources */,
Expand Down Expand Up @@ -1159,6 +1169,7 @@
D2D215DF27AC276700A104B8 /* CodingKey+JSON.swift in Sources */,
D2D215E027AC276700A104B8 /* GetConfigInteractor.swift in Sources */,
D2D215E127AC276700A104B8 /* ActionNotificationNetworkDataSource.swift in Sources */,
9415C4822BD933A50099C470 /* DeleteAPNSTokenQuery.swift in Sources */,
D2D215E227AC276700A104B8 /* DeleteConfigInteractor.swift in Sources */,
D2D215E327AC276700A104B8 /* NotificationNetworkDataSource.swift in Sources */,
D2D215E427AC276700A104B8 /* PushSubscription.swift in Sources */,
Expand Down Expand Up @@ -1214,6 +1225,7 @@
D2D2161127AC276700A104B8 /* MagicBellError.swift in Sources */,
D2D2161227AC276700A104B8 /* MagicBellClient.swift in Sources */,
D2D2161327AC276700A104B8 /* Environment.swift in Sources */,
9415C4852BD933AA0099C470 /* DeleteAPNSTokenInteractor.swift in Sources */,
D2D2161427AC276700A104B8 /* User.swift in Sources */,
D2D2161527AC276700A104B8 /* EncodableToDataMapper.swift in Sources */,
9415C47D2BD932D30099C470 /* RegisterAPNSTokensInteractor.swift in Sources */,
Expand Down
22 changes: 19 additions & 3 deletions Source/Features/APNSToken/APNSTokenDirector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,27 @@ import Harmony
protocol APNSTokenDirector {
/// Registers an APNS token
func registerAPNSToken(_ deviceToken: String)

/// Deletes an APNS token on logout
func deleteAPNSToken(_ deviceToken: String)
}

class DefaultAPNSTokenDirector: APNSTokenDirector {
private let logger: Logger
private let userQuery: UserQuery
private let registerAPNSTokensInteractor: RegisterAPNSTokensInteractor
private let registerAPNSTokenInteractor: RegisterAPNSTokenInteractor
private let deleteAPNSTokenInteractor: DeleteAPNSTokenInteractor

init(
logger: Logger,
userQuery: UserQuery,
registerAPNSTokensInteractor: RegisterAPNSTokensInteractor
registerAPNSTokenInteractor: RegisterAPNSTokenInteractor,
deleteAPNSTokenInteractor: DeleteAPNSTokenInteractor
) {
self.logger = logger
self.userQuery = userQuery
self.registerAPNSTokensInteractor = registerAPNSTokensInteractor
self.registerAPNSTokenInteractor = registerAPNSTokenInteractor
self.deleteAPNSTokenInteractor = deleteAPNSTokenInteractor
}

func registerAPNSToken(_ deviceToken: String) {
Expand All @@ -46,4 +52,14 @@ class DefaultAPNSTokenDirector: APNSTokenDirector {
}
}
}

func deleteAPNSToken(_ deviceToken: String) {
deleteAPNSTokenInteractor
.execute(deviceToken: deviceToken, userQuery: userQuery)
.then { apnsToken in
self.logger.info(tag: magicBellTag, "APNS token was deleted \(apnsToken)")
}.fail { error in
self.logger.info(tag: magicBellTag, "Deleting APNS token failed: \(error.localizedDescription)")
}
}
}
19 changes: 17 additions & 2 deletions Source/Features/APNSToken/APNSTokenProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ class DefaultAPNSTokenModule: APNSTokenComponent {
DefaultAPNSTokenDirector(
logger: logger,
userQuery: userQuery,
registerAPNSTokensInteractor: getRegisterAPNSTokenInteractor()
registerAPNSTokenInteractor: getRegisterAPNSTokenInteractor(),
deleteAPNSTokenInteractor: getDeleteAPNSTokenInteractor()
)
}

Expand All @@ -52,16 +53,30 @@ class DefaultAPNSTokenModule: APNSTokenComponent {
)
}


private func getDeleteAPNSTokenInteractor() -> DeleteAPNSTokenInteractor {
DeleteAPNSTokenInteractor(
executor: executor,
deleteAPNSTokenInteractor: deleteAPNSTokenInteractor,
logger: logger
)
}

private var putAPNSTokenInteractor: Interactor.PutByQuery<APNSToken> {
apnsTokenRepository.toPutByQueryInteractor(executor)
}

private var deleteAPNSTokenInteractor: Interactor.DeleteByQuery {
apnsTokenRepository.toDeleteByQueryInteractor(executor)
}

private lazy var apnsTokenRepository: AnyRepository<APNSToken> = {
let apnsTokenNetworkDataSource = APNSTokenNetworkDataSource(
httpClient: httpClient,
mapper: DataToDecodableMapper<APNSToken>()
)
let assembleAPNSTokenNetworkDataSource = DataSourceAssembler(put: apnsTokenNetworkDataSource)
let assembleAPNSTokenNetworkDataSource = DataSourceAssembler(put: apnsTokenNetworkDataSource,
delete: apnsTokenNetworkDataSource)
return AnyRepository(SingleDataSourceRepository(assembleAPNSTokenNetworkDataSource))
}()
}
29 changes: 28 additions & 1 deletion Source/Features/APNSToken/Data/APNSTokenNetworkDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import Foundation
import Harmony

class APNSTokenNetworkDataSource: PutDataSource {
class APNSTokenNetworkDataSource: PutDataSource, DeleteDataSource {
typealias T = APNSToken

private let httpClient: HttpClient
Expand Down Expand Up @@ -61,4 +61,31 @@ class APNSTokenNetworkDataSource: PutDataSource {
assertionFailure("Should never happen")
return Future(CoreError.NotImplemented())
}

func delete(_ query: Harmony.Query) -> Harmony.Future<Void> {
guard let query = query as? DeleteAPNSTokenQuery else {
assertionFailure("Should never happen")
return Future(CoreError.Failed("Invalid Query"))
}

let user = query.user
let deviceToken = query.deviceToken

var urlRequest = httpClient.prepareURLRequest(
path: "/channels/mobile_push/apns/tokens/\(deviceToken)",
externalId: user.externalId,
email: user.email,
hmac: user.hmac
)
urlRequest.httpMethod = "DELETE"

return self.httpClient
.performRequest(urlRequest)
.map { _ in Void() }
}

func deleteAll(_ query: Harmony.Query) -> Harmony.Future<Void> {
assertionFailure("Should never happen")
return Future(CoreError.NotImplemented())
}
}
24 changes: 24 additions & 0 deletions Source/Features/APNSToken/Data/DeleteAPNSTokenQuery.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// By downloading or using this software made available by MagicBell, Inc.
// ("MagicBell") or any documentation that accompanies it (collectively, the
// "Software"), you and the company or entity that you represent (collectively,
// "you" or "your") are consenting to be bound by and are becoming a party to this
// License Agreement (this "Agreement"). You hereby represent and warrant that you
// are authorized and lawfully able to bind such company or entity that you
// represent to this Agreement. If you do not have such authority or do not agree
// to all of the terms of this Agreement, you may not download or use the Software.
//
// For more information, read the LICENSE file.
//

import Harmony

class DeleteAPNSTokenQuery: Query {
let user: UserQuery
let deviceToken: String

init(user: UserQuery, deviceToken: String) {
self.user = user
self.deviceToken = deviceToken
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// By downloading or using this software made available by MagicBell, Inc.
// ("MagicBell") or any documentation that accompanies it (collectively, the
// "Software"), you and the company or entity that you represent (collectively,
// "you" or "your") are consenting to be bound by and are becoming a party to this
// License Agreement (this "Agreement"). You hereby represent and warrant that you
// are authorized and lawfully able to bind such company or entity that you
// represent to this Agreement. If you do not have such authority or do not agree
// to all of the terms of this Agreement, you may not download or use the Software.
//
// For more information, read the LICENSE file.
//

import Harmony

struct DeleteAPNSTokenInteractor {
private let executor: Executor
private let deleteAPNSTokenInteractor: Interactor.DeleteByQuery
private let logger: Logger

init(
executor: Executor,
deleteAPNSTokenInteractor: Interactor.DeleteByQuery,
logger: Logger
) {
self.executor = executor
self.deleteAPNSTokenInteractor = deleteAPNSTokenInteractor
self.logger = logger
}

func execute(deviceToken: String, userQuery: UserQuery) -> Future<Void> {
executor.submit { resolver in
let apnsTokenSubscriptionQuery = DeleteAPNSTokenQuery(user: userQuery, deviceToken: deviceToken)
resolver.set(deleteAPNSTokenInteractor.execute(apnsTokenSubscriptionQuery,
in: DirectExecutor()))
}
}
}
2 changes: 1 addition & 1 deletion Source/User.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class User {
func logout(deviceToken: String?) {
internalStoreDirector.logout()
if let deviceToken = deviceToken {
// TODO: Delete apnsToken
apnsToken.deleteAPNSToken(deviceToken)
pushSubscription.deletePushSubscription(deviceToken)
}
}
Expand Down

0 comments on commit 02c1723

Please sign in to comment.