fix iOS topic normalization and refresh after test push
This commit is contained in:
parent
3feb27848a
commit
9ec3c22317
8 changed files with 61 additions and 33 deletions
|
|
@ -142,14 +142,15 @@ extension AppDelegate: MessagingDelegate {
|
|||
|
||||
// Re-subscribe to Firebase for all topics
|
||||
let store = Store.shared
|
||||
let subscriptionManager = SubscriptionManager(store: store)
|
||||
store.getSubscriptions()?.forEach{ subscription in
|
||||
if let baseUrl = subscription.baseUrl, let topic = subscription.topic {
|
||||
Log.d(tag, "Re-subscribing to topic \(baseUrl)/\(topic)")
|
||||
if baseUrl == Config.appBaseUrl {
|
||||
Messaging.messaging().subscribe(toTopic: topic)
|
||||
} else {
|
||||
Messaging.messaging().subscribe(toTopic: topicHash(baseUrl: baseUrl, topic: topic))
|
||||
if normalizeBaseUrl(baseUrl) == "https://ntfy.sh" && normalizeBaseUrl(Config.appBaseUrl) != "https://ntfy.sh" {
|
||||
subscriptionManager.rebase(subscription, to: Config.appBaseUrl)
|
||||
return
|
||||
}
|
||||
Messaging.messaging().subscribe(toTopic: firebaseTopic(baseUrl: baseUrl, topic: topic))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,10 +77,10 @@ class Store: ObservableObject {
|
|||
|
||||
func saveSubscription(baseUrl: String, topic: String) -> Subscription {
|
||||
let subscription = Subscription(context: context)
|
||||
subscription.baseUrl = baseUrl
|
||||
subscription.baseUrl = normalizeBaseUrl(baseUrl)
|
||||
subscription.topic = topic
|
||||
DispatchQueue.main.sync {
|
||||
Log.d(Store.tag, "Storing subscription baseUrl=\(baseUrl), topic=\(topic)")
|
||||
Log.d(Store.tag, "Storing subscription baseUrl=\(subscription.baseUrl ?? "?"), topic=\(topic)")
|
||||
try? context.save()
|
||||
}
|
||||
return subscription
|
||||
|
|
@ -88,7 +88,7 @@ class Store: ObservableObject {
|
|||
|
||||
func getSubscription(baseUrl: String, topic: String) -> Subscription? {
|
||||
let fetchRequest = Subscription.fetchRequest()
|
||||
let baseUrlPredicate = NSPredicate(format: "baseUrl = %@", baseUrl)
|
||||
let baseUrlPredicate = NSPredicate(format: "baseUrl = %@", normalizeBaseUrl(baseUrl))
|
||||
let topicPredicate = NSPredicate(format: "topic = %@", topic)
|
||||
|
||||
fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [baseUrlPredicate, topicPredicate])
|
||||
|
|
@ -99,6 +99,11 @@ class Store: ObservableObject {
|
|||
func getSubscriptions() -> [Subscription]? {
|
||||
return try? context.fetch(Subscription.fetchRequest())
|
||||
}
|
||||
|
||||
func updateSubscriptionBaseUrl(_ subscription: Subscription, baseUrl: String) {
|
||||
subscription.baseUrl = normalizeBaseUrl(baseUrl)
|
||||
try? context.save()
|
||||
}
|
||||
|
||||
func delete(subscription: Subscription) {
|
||||
context.delete(subscription)
|
||||
|
|
@ -167,7 +172,7 @@ class Store: ObservableObject {
|
|||
func saveUser(baseUrl: String, username: String, password: String) {
|
||||
do {
|
||||
let user = getUser(baseUrl: baseUrl) ?? User(context: context)
|
||||
user.baseUrl = baseUrl
|
||||
user.baseUrl = normalizeBaseUrl(baseUrl)
|
||||
user.username = username
|
||||
user.password = password
|
||||
try context.save()
|
||||
|
|
@ -179,7 +184,7 @@ class Store: ObservableObject {
|
|||
|
||||
func getUser(baseUrl: String) -> User? {
|
||||
let request = User.fetchRequest()
|
||||
request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [NSPredicate(format: "baseUrl = %@", baseUrl)])
|
||||
request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [NSPredicate(format: "baseUrl = %@", normalizeBaseUrl(baseUrl))])
|
||||
return try? context.fetch(request).first
|
||||
}
|
||||
|
||||
|
|
@ -194,7 +199,7 @@ class Store: ObservableObject {
|
|||
do {
|
||||
let pref = getPreference(key: Store.prefKeyDefaultBaseUrl) ?? Preference(context: context)
|
||||
pref.key = Store.prefKeyDefaultBaseUrl
|
||||
pref.value = baseUrl ?? Config.appBaseUrl
|
||||
pref.value = baseUrl.map(normalizeBaseUrl) ?? Config.appBaseUrl
|
||||
try context.save()
|
||||
} catch let error {
|
||||
Log.w(Store.tag, "Cannot store preference", error)
|
||||
|
|
@ -207,7 +212,7 @@ class Store: ObservableObject {
|
|||
if baseUrl == nil || baseUrl?.isEmpty == true {
|
||||
return Config.appBaseUrl
|
||||
}
|
||||
return baseUrl!
|
||||
return normalizeBaseUrl(baseUrl!)
|
||||
}
|
||||
|
||||
private func getPreference(key: String) -> Preference? {
|
||||
|
|
|
|||
|
|
@ -8,13 +8,10 @@ struct SubscriptionManager {
|
|||
var store: Store
|
||||
|
||||
func subscribe(baseUrl: String, topic: String) {
|
||||
Log.d(tag, "Subscribing to \(topicUrl(baseUrl: baseUrl, topic: topic))")
|
||||
if baseUrl == Config.appBaseUrl {
|
||||
Messaging.messaging().subscribe(toTopic: topic)
|
||||
} else {
|
||||
Messaging.messaging().subscribe(toTopic: topicHash(baseUrl: baseUrl, topic: topic))
|
||||
}
|
||||
let subscription = store.saveSubscription(baseUrl: baseUrl, topic: topic)
|
||||
let normalizedBaseUrl = normalizeBaseUrl(baseUrl)
|
||||
Log.d(tag, "Subscribing to \(topicUrl(baseUrl: normalizedBaseUrl, topic: topic))")
|
||||
Messaging.messaging().subscribe(toTopic: firebaseTopic(baseUrl: normalizedBaseUrl, topic: topic))
|
||||
let subscription = store.saveSubscription(baseUrl: normalizedBaseUrl, topic: topic)
|
||||
poll(subscription)
|
||||
}
|
||||
|
||||
|
|
@ -22,15 +19,21 @@ struct SubscriptionManager {
|
|||
Log.d(tag, "Unsubscribing from \(subscription.urlString())")
|
||||
DispatchQueue.main.async {
|
||||
if let baseUrl = subscription.baseUrl, let topic = subscription.topic {
|
||||
if baseUrl == Config.appBaseUrl {
|
||||
Messaging.messaging().unsubscribe(fromTopic: topic)
|
||||
} else {
|
||||
Messaging.messaging().unsubscribe(fromTopic: topicHash(baseUrl: baseUrl, topic: topic))
|
||||
}
|
||||
Messaging.messaging().unsubscribe(fromTopic: firebaseTopic(baseUrl: baseUrl, topic: topic))
|
||||
}
|
||||
store.delete(subscription: subscription)
|
||||
}
|
||||
}
|
||||
|
||||
func rebase(_ subscription: Subscription, to baseUrl: String) {
|
||||
guard let oldBaseUrl = subscription.baseUrl, let topic = subscription.topic else { return }
|
||||
let normalizedBaseUrl = normalizeBaseUrl(baseUrl)
|
||||
if normalizeBaseUrl(oldBaseUrl) == normalizedBaseUrl { return }
|
||||
Log.d(tag, "Updating subscription \(topic) from \(oldBaseUrl) to \(normalizedBaseUrl)")
|
||||
Messaging.messaging().unsubscribe(fromTopic: firebaseTopic(baseUrl: oldBaseUrl, topic: topic))
|
||||
Messaging.messaging().subscribe(toTopic: firebaseTopic(baseUrl: normalizedBaseUrl, topic: topic))
|
||||
store.updateSubscriptionBaseUrl(subscription, baseUrl: normalizedBaseUrl)
|
||||
}
|
||||
|
||||
func poll(_ subscription: Subscription) {
|
||||
poll(subscription) { _ in }
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@ class ApiService {
|
|||
message: String,
|
||||
title: String,
|
||||
priority: Int = 3,
|
||||
tags: [String] = []
|
||||
tags: [String] = [],
|
||||
completionHandler: (() -> Void)? = nil
|
||||
) {
|
||||
guard let url = URL(string: subscription.urlString()) else { return }
|
||||
var request = newRequest(url: url, user: user)
|
||||
|
|
@ -61,6 +62,7 @@ class ApiService {
|
|||
return
|
||||
}
|
||||
Log.d(self.tag, "Publishing message succeeded", response)
|
||||
completionHandler?()
|
||||
}.resume()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import Foundation
|
|||
import CryptoKit
|
||||
|
||||
func topicUrl(baseUrl: String, topic: String) -> String {
|
||||
return "\(baseUrl)/\(topic)"
|
||||
return "\(normalizeBaseUrl(baseUrl))/\(topic)"
|
||||
}
|
||||
|
||||
func topicShortUrl(baseUrl: String, topic: String) -> String {
|
||||
|
|
@ -10,15 +10,29 @@ func topicShortUrl(baseUrl: String, topic: String) -> String {
|
|||
}
|
||||
|
||||
func topicAuthUrl(baseUrl: String, topic: String) -> String {
|
||||
return "\(baseUrl)/\(topic)/auth"
|
||||
return "\(normalizeBaseUrl(baseUrl))/\(topic)/auth"
|
||||
}
|
||||
|
||||
func topicHash(baseUrl: String, topic: String) -> String {
|
||||
let data = Data(topicUrl(baseUrl: baseUrl, topic: topic).utf8)
|
||||
let data = Data(topicUrl(baseUrl: normalizeBaseUrl(baseUrl), topic: topic).utf8)
|
||||
let digest = SHA256.hash(data: data)
|
||||
return digest.compactMap { String(format: "%02x", $0)}.joined()
|
||||
}
|
||||
|
||||
func firebaseTopic(baseUrl: String, topic: String) -> String {
|
||||
return normalizeBaseUrl(baseUrl) == normalizeBaseUrl(Config.appBaseUrl)
|
||||
? topic
|
||||
: topicHash(baseUrl: baseUrl, topic: topic)
|
||||
}
|
||||
|
||||
func normalizeBaseUrl(_ baseUrl: String) -> String {
|
||||
var normalized = baseUrl.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
while normalized.hasSuffix("/") {
|
||||
normalized.removeLast()
|
||||
}
|
||||
return normalized
|
||||
}
|
||||
|
||||
func shortUrl(url: String) -> String {
|
||||
return url
|
||||
.replacingOccurrences(of: "http://", with: "")
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ enum ActiveAlert {
|
|||
case clear, unsubscribe, selected
|
||||
}
|
||||
|
||||
|
||||
struct NotificationListView: View {
|
||||
private let tag = "NotificationListView"
|
||||
|
||||
|
|
@ -201,7 +202,9 @@ struct NotificationListView: View {
|
|||
title: "Test: You can set a title if you like",
|
||||
priority: priority,
|
||||
tags: tags
|
||||
)
|
||||
) {
|
||||
subscriptionManager.poll(subscription)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ struct DefaultServerView: View {
|
|||
if newDefaultBaseUrl == "" {
|
||||
store.saveDefaultBaseUrl(baseUrl: nil)
|
||||
} else {
|
||||
store.saveDefaultBaseUrl(baseUrl: newDefaultBaseUrl)
|
||||
store.saveDefaultBaseUrl(baseUrl: normalizeBaseUrl(newDefaultBaseUrl))
|
||||
}
|
||||
resetAndHide()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ struct SubscriptionAddView: View {
|
|||
return false
|
||||
} else if selectedBaseUrl.range(of: "^https?://.+", options: .regularExpression, range: nil, locale: nil) == nil {
|
||||
return false
|
||||
} else if store.getSubscription(baseUrl: selectedBaseUrl, topic: topic) != nil {
|
||||
} else if store.getSubscription(baseUrl: selectedBaseUrl, topic: sanitizedTopic) != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
|
@ -153,7 +153,7 @@ struct SubscriptionAddView: View {
|
|||
loading = true
|
||||
addError = nil
|
||||
let user = store.getUser(baseUrl: selectedBaseUrl)?.toBasicUser()
|
||||
ApiService.shared.checkAuth(baseUrl: selectedBaseUrl, topic: topic, user: user) { result in
|
||||
ApiService.shared.checkAuth(baseUrl: selectedBaseUrl, topic: sanitizedTopic, user: user) { result in
|
||||
switch result {
|
||||
case .Success:
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
|
|
@ -180,7 +180,7 @@ struct SubscriptionAddView: View {
|
|||
loading = true
|
||||
loginError = nil
|
||||
let user = BasicUser(username: username, password: password)
|
||||
ApiService.shared.checkAuth(baseUrl: selectedBaseUrl, topic: topic, user: user) { result in
|
||||
ApiService.shared.checkAuth(baseUrl: selectedBaseUrl, topic: sanitizedTopic, user: user) { result in
|
||||
switch result {
|
||||
case .Success:
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
|
|
@ -204,7 +204,7 @@ struct SubscriptionAddView: View {
|
|||
}
|
||||
|
||||
private var selectedBaseUrl: String {
|
||||
return (useAnother) ? baseUrl : store.getDefaultBaseUrl()
|
||||
return normalizeBaseUrl((useAnother) ? baseUrl : store.getDefaultBaseUrl())
|
||||
}
|
||||
|
||||
private func resetAndHide() {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue