handle network switching on logout

This commit is contained in:
mertalev 2026-03-10 12:26:58 -05:00
parent 66e678e7f5
commit f6f999e32b
No known key found for this signature in database
GPG Key ID: DF6ABC77AAD98C95
2 changed files with 38 additions and 19 deletions

View File

@ -17,7 +17,6 @@ import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.io.ByteArrayInputStream
import java.io.File
@ -315,7 +314,7 @@ object HttpClientManager {
val parsed = urls.mapNotNull { it.toHttpUrlOrNull() }
if (parsed.map { it.host } == serverUrls.map { it.host }) return
serverUrls = parsed
if (duplicateAuthCookies()) persist()
if (syncAuthCookies()) persist()
}
@Synchronized
@ -327,20 +326,30 @@ object HttpClientManager {
cookies.any { it.name == existing.name && it.domain == existing.domain && it.path == existing.path }
}
store.addAll(cookies)
val duplicated = serverUrls.any { it.host == url.host } && duplicateAuthCookies()
if (changed || duplicated) persist()
val synced = serverUrls.any { it.host == url.host } && syncAuthCookies()
if (changed || synced) persist()
}
@Synchronized
override fun loadForRequest(url: HttpUrl): List<Cookie> {
val now = System.currentTimeMillis()
store.removeAll { it.expiresAt < now }
if (store.removeAll { it.expiresAt < now }) {
syncAuthCookies()
persist()
}
return store.filter { it.matches(url) }
}
private fun duplicateAuthCookies(): Boolean {
val sourceCookies = store.filter { it.name in AUTH_COOKIE_NAMES }.associateBy { it.name }
if (sourceCookies.isEmpty()) return false
private fun syncAuthCookies(): Boolean {
val serverHosts = serverUrls.map { it.host }.toSet()
val now = System.currentTimeMillis()
val sourceCookies = store
.filter { it.name in AUTH_COOKIE_NAMES && it.domain in serverHosts && it.expiresAt > now }
.associateBy { it.name }
if (sourceCookies.isEmpty()) {
return store.removeAll { it.name in AUTH_COOKIE_NAMES && it.domain in serverHosts }
}
var changed = false
for (url in serverUrls) {

View File

@ -3,7 +3,6 @@ import native_video_player
let CLIENT_CERT_LABEL = "app.alextran.immich.client_identity"
let HEADERS_KEY = "immich.request_headers"
let SERVER_URL_KEY = "immich.server_url"
let SERVER_URLS_KEY = "immich.server_urls"
let APP_GROUP = "group.app.immich.share"
@ -36,7 +35,7 @@ class URLSessionManager: NSObject {
}()
static let cookieStorage = HTTPCookieStorage.sharedCookieStorage(forGroupContainerIdentifier: APP_GROUP)
private static var serverUrls: [String] = []
private static var isDuplicating = false
private static var isSyncing = false
var sessionPointer: UnsafeMutableRawPointer {
Unmanaged.passUnretained(session).toOpaque()
@ -63,29 +62,40 @@ class URLSessionManager: NSObject {
guard urls != serverUrls else { return }
serverUrls = urls
UserDefaults.group.set(urls, forKey: SERVER_URLS_KEY)
duplicateAuthCookies()
syncAuthCookies()
}
@objc private static func cookiesDidChange(_ notification: Notification) {
guard !isDuplicating, !serverUrls.isEmpty else { return }
duplicateAuthCookies()
guard !isSyncing, !serverUrls.isEmpty else { return }
syncAuthCookies()
}
private static func duplicateAuthCookies() {
private static func syncAuthCookies() {
let authCookieNames: Set<String> = ["immich_access_token", "immich_is_authenticated", "immich_auth_type"]
let serverHosts = Set(serverUrls.compactMap { URL(string: $0)?.host })
let allCookies = cookieStorage.cookies ?? []
let now = Date()
let serverAuthCookies = allCookies.filter {
authCookieNames.contains($0.name) && serverHosts.contains($0.domain)
}
var sourceCookies: [String: HTTPCookie] = [:]
for cookie in allCookies {
if authCookieNames.contains(cookie.name) {
for cookie in serverAuthCookies {
if cookie.expiresDate.map({ $0 > now }) ?? true {
sourceCookies[cookie.name] = cookie
}
}
guard !sourceCookies.isEmpty else { return }
isSyncing = true
defer { isSyncing = false }
isDuplicating = true
defer { isDuplicating = false }
if sourceCookies.isEmpty {
for cookie in serverAuthCookies {
cookieStorage.deleteCookie(cookie)
}
return
}
for serverUrl in serverUrls {
guard let url = URL(string: serverUrl), let domain = url.host else { continue }