Add AuthManager OSLog tracing and fix URL construction in APIEndpoints

This commit is contained in:
2026-02-19 18:58:31 +01:00
parent 1aac76af4a
commit 062af3b2da
2 changed files with 19 additions and 2 deletions

View File

@@ -1,5 +1,8 @@
import Foundation import Foundation
import KeychainAccess import KeychainAccess
import OSLog
private let logger = Logger(subsystem: "com.timetracker.app", category: "AuthManager")
@MainActor @MainActor
final class AuthManager: ObservableObject { final class AuthManager: ObservableObject {
@@ -29,19 +32,23 @@ final class AuthManager: ObservableObject {
} }
func checkAuthState() async { func checkAuthState() async {
guard accessToken != nil else { guard let token = accessToken else {
logger.info("checkAuthState — no token in keychain, not authenticated")
isAuthenticated = false isAuthenticated = false
return return
} }
logger.info("checkAuthState — token found (first 20 chars: \(token.prefix(20))…), calling /auth/me")
do { do {
let user: User = try await apiClient.request( let user: User = try await apiClient.request(
endpoint: APIEndpoint.me, endpoint: APIEndpoint.me,
authenticated: true authenticated: true
) )
logger.info("checkAuthState — /auth/me OK, user: \(user.id)")
currentUser = user currentUser = user
isAuthenticated = true isAuthenticated = true
} catch { } catch {
logger.error("checkAuthState — /auth/me failed: \(error.localizedDescription) — clearing auth")
clearAuth() clearAuth()
} }
} }
@@ -67,15 +74,18 @@ final class AuthManager: ObservableObject {
} }
func clearAuth() { func clearAuth() {
logger.info("clearAuth — wiping token and user")
accessToken = nil accessToken = nil
currentUser = nil currentUser = nil
isAuthenticated = false isAuthenticated = false
} }
func handleTokenResponse(_ response: TokenResponse) async { func handleTokenResponse(_ response: TokenResponse) async {
logger.info("handleTokenResponse — storing JWT for user \(response.user.id)")
accessToken = response.accessToken accessToken = response.accessToken
currentUser = response.user currentUser = response.user
isAuthenticated = true isAuthenticated = true
logger.info("handleTokenResponse — isAuthenticated = true, token stored: \(self.accessToken != nil)")
} }
var loginURL: URL { var loginURL: URL {

View File

@@ -29,6 +29,13 @@ enum APIEndpoint {
struct APIEndpoints { struct APIEndpoints {
static func url(for endpoint: String) -> URL { static func url(for endpoint: String) -> URL {
AppConfig.apiBaseURL.appendingPathComponent(endpoint) // Use URL(string:relativeTo:) rather than appendingPathComponent so that
// leading slashes in endpoint strings are handled correctly and don't
// accidentally replace or duplicate the base URL path.
let base = AppConfig.apiBaseURL.absoluteString.hasSuffix("/")
? AppConfig.apiBaseURL
: URL(string: AppConfig.apiBaseURL.absoluteString + "/")!
let relative = endpoint.hasPrefix("/") ? String(endpoint.dropFirst()) : endpoint
return URL(string: relative, relativeTo: base)!.absoluteURL
} }
} }