From 696f1d1d4a55a6a55b2ac76dd9a4930c19dbeaf1 Mon Sep 17 00:00:00 2001 From: mertalev <101130780+mertalev@users.noreply.github.com> Date: Tue, 10 Mar 2026 12:43:48 -0500 Subject: [PATCH] remove bootstrapCookies --- .../alextran/immich/core/HttpClientManager.kt | 34 +++++------ .../app/alextran/immich/core/Network.g.kt | 25 +-------- .../alextran/immich/core/NetworkApiPlugin.kt | 8 +-- mobile/ios/Runner/Core/Network.g.swift | 22 +------- mobile/ios/Runner/Core/NetworkApiImpl.swift | 56 +++++++++---------- .../repositories/network.repository.dart | 4 +- mobile/lib/platform/network_api.g.dart | 27 +-------- mobile/lib/utils/migration.dart | 3 +- mobile/pigeon/network_api.dart | 4 +- 9 files changed, 60 insertions(+), 123 deletions(-) diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/core/HttpClientManager.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/core/HttpClientManager.kt index bdec3a21df..feba043e02 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/core/HttpClientManager.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/core/HttpClientManager.kt @@ -168,7 +168,7 @@ object HttpClientManager { synchronized(this) { clientChangedListeners.add(listener) } } - fun setRequestHeaders(headerMap: Map, serverUrls: List) { + fun setRequestHeaders(headerMap: Map, serverUrls: List, token: String?) { synchronized(this) { val builder = Headers.Builder() headerMap.forEach { (key, value) -> builder[key] = value } @@ -186,23 +186,23 @@ object HttpClientManager { putString(PREFS_SERVER_URLS, Json.encodeToString(serverUrls)) } } - } - } - fun bootstrapCookies(token: String, serverUrls: List) { - val url = serverUrls.firstNotNullOfOrNull { it.toHttpUrlOrNull() } ?: return - val expiry = System.currentTimeMillis() + 400L * 24 * 60 * 60 * 1000 - fun cookie(name: String, value: String, httpOnly: Boolean) = - Cookie.Builder().name(name).value(value).domain(url.host).path("/").expiresAt(expiry) - .apply { - if (url.isHttps) secure() - if (httpOnly) httpOnly() - }.build() - cookieJar.saveFromResponse(url, listOf( - cookie("immich_access_token", token, httpOnly = true), - cookie("immich_is_authenticated", "true", httpOnly = false), - cookie("immich_auth_type", "password", httpOnly = true), - )) + if (token != null) { + val url = serverUrls.firstNotNullOfOrNull { it.toHttpUrlOrNull() } ?: return + val expiry = System.currentTimeMillis() + 400L * 24 * 60 * 60 * 1000 + fun cookie(name: String, value: String, httpOnly: Boolean) = + Cookie.Builder().name(name).value(value).domain(url.host).path("/").expiresAt(expiry) + .apply { + if (url.isHttps) secure() + if (httpOnly) httpOnly() + }.build() + cookieJar.saveFromResponse(url, listOf( + cookie("immich_access_token", token, httpOnly = true), + cookie("immich_is_authenticated", "true", httpOnly = false), + cookie("immich_auth_type", "password", httpOnly = true), + )) + } + } } fun loadCookieHeader(url: String): String? { diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/core/Network.g.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/core/Network.g.kt index f40f29cb5b..869e312515 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/core/Network.g.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/core/Network.g.kt @@ -184,8 +184,7 @@ interface NetworkApi { fun removeCertificate(callback: (Result) -> Unit) fun hasCertificate(): Boolean fun getClientPointer(): Long - fun setRequestHeaders(headers: Map, serverUrls: List) - fun bootstrapCookies(token: String, serverUrls: List) + fun setRequestHeaders(headers: Map, serverUrls: List, token: String?) companion object { /** The codec used by NetworkApi. */ @@ -288,27 +287,9 @@ interface NetworkApi { val args = message as List val headersArg = args[0] as Map val serverUrlsArg = args[1] as List + val tokenArg = args[2] as String? val wrapped: List = try { - api.setRequestHeaders(headersArg, serverUrlsArg) - listOf(null) - } catch (exception: Throwable) { - NetworkPigeonUtils.wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.immich_mobile.NetworkApi.bootstrapCookies$separatedMessageChannelSuffix", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val tokenArg = args[0] as String - val serverUrlsArg = args[1] as List - val wrapped: List = try { - api.bootstrapCookies(tokenArg, serverUrlsArg) + api.setRequestHeaders(headersArg, serverUrlsArg, tokenArg) listOf(null) } catch (exception: Throwable) { NetworkPigeonUtils.wrapError(exception) diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/core/NetworkApiPlugin.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/core/NetworkApiPlugin.kt index 57b2cc9397..85b7a6c730 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/core/NetworkApiPlugin.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/core/NetworkApiPlugin.kt @@ -79,11 +79,7 @@ private class NetworkApiImpl : NetworkApi { return HttpClientManager.getClientPointer() } - override fun setRequestHeaders(headers: Map, serverUrls: List) { - HttpClientManager.setRequestHeaders(headers, serverUrls) - } - - override fun bootstrapCookies(token: String, serverUrls: List) { - HttpClientManager.bootstrapCookies(token, serverUrls) + override fun setRequestHeaders(headers: Map, serverUrls: List, token: String?) { + HttpClientManager.setRequestHeaders(headers, serverUrls, token) } } diff --git a/mobile/ios/Runner/Core/Network.g.swift b/mobile/ios/Runner/Core/Network.g.swift index ecd5153378..5a8075f91a 100644 --- a/mobile/ios/Runner/Core/Network.g.swift +++ b/mobile/ios/Runner/Core/Network.g.swift @@ -225,8 +225,7 @@ protocol NetworkApi { func removeCertificate(completion: @escaping (Result) -> Void) func hasCertificate() throws -> Bool func getClientPointer() throws -> Int64 - func setRequestHeaders(headers: [String: String], serverUrls: [String]) throws - func bootstrapCookies(token: String, serverUrls: [String]) throws + func setRequestHeaders(headers: [String: String], serverUrls: [String], token: String?) throws } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. @@ -316,8 +315,9 @@ class NetworkApiSetup { let args = message as! [Any?] let headersArg = args[0] as! [String: String] let serverUrlsArg = args[1] as! [String] + let tokenArg: String? = nilOrValue(args[2]) do { - try api.setRequestHeaders(headers: headersArg, serverUrls: serverUrlsArg) + try api.setRequestHeaders(headers: headersArg, serverUrls: serverUrlsArg, token: tokenArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) @@ -326,21 +326,5 @@ class NetworkApiSetup { } else { setRequestHeadersChannel.setMessageHandler(nil) } - let bootstrapCookiesChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.NetworkApi.bootstrapCookies\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - bootstrapCookiesChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let tokenArg = args[0] as! String - let serverUrlsArg = args[1] as! [String] - do { - try api.bootstrapCookies(token: tokenArg, serverUrls: serverUrlsArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - bootstrapCookiesChannel.setMessageHandler(nil) - } } } diff --git a/mobile/ios/Runner/Core/NetworkApiImpl.swift b/mobile/ios/Runner/Core/NetworkApiImpl.swift index ad1d9b63a0..310ff28a44 100644 --- a/mobile/ios/Runner/Core/NetworkApiImpl.swift +++ b/mobile/ios/Runner/Core/NetworkApiImpl.swift @@ -58,41 +58,41 @@ class NetworkApiImpl: NetworkApi { return Int64(Int(bitPattern: pointer)) } - func setRequestHeaders(headers: [String : String], serverUrls: [String]) throws { + func setRequestHeaders(headers: [String : String], serverUrls: [String], token: String?) throws { URLSessionManager.setServerUrls(serverUrls) + if let token = token { + let expiry = Date().addingTimeInterval(400 * 24 * 60 * 60) + for serverUrl in serverUrls { + guard let url = URL(string: serverUrl), let domain = url.host else { continue } + let isSecure = serverUrl.hasPrefix("https") + let cookies: [(String, String, Bool)] = [ + ("immich_access_token", token, true), + ("immich_is_authenticated", "true", false), + ("immich_auth_type", "password", true), + ] + for (name, value, httpOnly) in cookies { + var properties: [HTTPCookiePropertyKey: Any] = [ + .name: name, + .value: value, + .domain: domain, + .path: "/", + .expires: expiry, + ] + if isSecure { properties[.secure] = "TRUE" } + if httpOnly { properties[.init("HttpOnly")] = "TRUE" } + if let cookie = HTTPCookie(properties: properties) { + URLSessionManager.cookieStorage.setCookie(cookie) + } + } + } + } + if headers != UserDefaults.group.dictionary(forKey: HEADERS_KEY) as? [String: String] { UserDefaults.group.set(headers, forKey: HEADERS_KEY) URLSessionManager.shared.recreateSession() } } - - func bootstrapCookies(token: String, serverUrls: [String]) throws { - let expiry = Date().addingTimeInterval(400 * 24 * 60 * 60) - for serverUrl in serverUrls { - guard let url = URL(string: serverUrl), let domain = url.host else { continue } - let isSecure = serverUrl.hasPrefix("https") - let cookies: [(String, String, Bool)] = [ - ("immich_access_token", token, true), - ("immich_is_authenticated", "true", false), - ("immich_auth_type", "password", true), - ] - for (name, value, httpOnly) in cookies { - var properties: [HTTPCookiePropertyKey: Any] = [ - .name: name, - .value: value, - .domain: domain, - .path: "/", - .expires: expiry, - ] - if isSecure { properties[.secure] = "TRUE" } - if httpOnly { properties[.init("HttpOnly")] = "TRUE" } - if let cookie = HTTPCookie(properties: properties) { - URLSessionManager.cookieStorage.setCookie(cookie) - } - } - } - } } private class CertImporter: NSObject, UIDocumentPickerDelegate { diff --git a/mobile/lib/infrastructure/repositories/network.repository.dart b/mobile/lib/infrastructure/repositories/network.repository.dart index adf1ee5694..bb5796e220 100644 --- a/mobile/lib/infrastructure/repositories/network.repository.dart +++ b/mobile/lib/infrastructure/repositories/network.repository.dart @@ -26,8 +26,8 @@ class NetworkRepository { } } - static Future setHeaders(Map headers, List serverUrls) async { - await networkApi.setRequestHeaders(headers, serverUrls); + static Future setHeaders(Map headers, List serverUrls, {String? token}) async { + await networkApi.setRequestHeaders(headers, serverUrls, token); if (Platform.isIOS) { await init(); } diff --git a/mobile/lib/platform/network_api.g.dart b/mobile/lib/platform/network_api.g.dart index 84050fd08a..af391b9a1a 100644 --- a/mobile/lib/platform/network_api.g.dart +++ b/mobile/lib/platform/network_api.g.dart @@ -301,37 +301,14 @@ class NetworkApi { } } - Future setRequestHeaders(Map headers, List serverUrls) async { + Future setRequestHeaders(Map headers, List serverUrls, String? token) async { final String pigeonVar_channelName = 'dev.flutter.pigeon.immich_mobile.NetworkApi.setRequestHeaders$pigeonVar_messageChannelSuffix'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([headers, serverUrls]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - Future bootstrapCookies(String token, List serverUrls) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.immich_mobile.NetworkApi.bootstrapCookies$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([token, serverUrls]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([headers, serverUrls, token]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { diff --git a/mobile/lib/utils/migration.dart b/mobile/lib/utils/migration.dart index e6302764b7..76916cee1e 100644 --- a/mobile/lib/utils/migration.dart +++ b/mobile/lib/utils/migration.dart @@ -25,6 +25,7 @@ import 'package:immich_mobile/infrastructure/entities/user.entity.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/sync_stream.repository.dart'; import 'package:immich_mobile/platform/native_sync_api.g.dart'; +import 'package:immich_mobile/infrastructure/repositories/network.repository.dart'; import 'package:immich_mobile/platform/network_api.g.dart'; import 'package:immich_mobile/providers/infrastructure/platform.provider.dart'; import 'package:immich_mobile/services/api.service.dart'; @@ -115,7 +116,7 @@ Future migrateDatabaseIfNeeded(Isar db, Drift drift) async { if (accessToken != null && accessToken.isNotEmpty) { final serverUrls = ApiService.getServerUrls(); if (serverUrls.isNotEmpty) { - await networkApi.bootstrapCookies(accessToken, serverUrls); + await NetworkRepository.setHeaders(ApiService.getRequestHeaders(), serverUrls, token: accessToken); } } } diff --git a/mobile/pigeon/network_api.dart b/mobile/pigeon/network_api.dart index 4878c627e4..704efed770 100644 --- a/mobile/pigeon/network_api.dart +++ b/mobile/pigeon/network_api.dart @@ -43,7 +43,5 @@ abstract class NetworkApi { int getClientPointer(); - void setRequestHeaders(Map headers, List serverUrls); - - void bootstrapCookies(String token, List serverUrls); + void setRequestHeaders(Map headers, List serverUrls, String? token); }