refactor: update Dockerfile paths, network module auth flow, and Keycloak config
Updated Dockerfiles to fix frontend path references after refactoring. Refactored `networkModule` to replace the `Auth` plugin with manual auth header injection for enhanced logout support. Adjusted Keycloak realm configuration to set default credentials as non-temporary. Improved error handling in `AuthApiClient` with detailed response messages.
This commit is contained in:
parent
a3ac6a52be
commit
48ee074dbd
|
|
@ -3,7 +3,7 @@
|
|||
# ===================================================================
|
||||
# Multi-stage Dockerfile for Meldestelle API Gateway
|
||||
# Features: Security hardening, monitoring support, optimal caching, BuildKit cache mounts
|
||||
# Version: 2.2.1 - Optimized for Monorepo (Fixed missing frontend dirs)
|
||||
# Version: 2.2.2 - Optimized for Monorepo (Fixed frontend paths after refactoring)
|
||||
# ===================================================================
|
||||
|
||||
# === CENTRALIZED BUILD ARGUMENTS ===
|
||||
|
|
@ -55,13 +55,13 @@ COPY contracts/ contracts/
|
|||
# Create dummy frontend directories to satisfy settings.gradle.kts include paths
|
||||
# This prevents Gradle from failing configuration phase without copying actual frontend code
|
||||
RUN mkdir -p \
|
||||
frontend/core/auth \
|
||||
frontend/core/domain \
|
||||
frontend/core/design-system \
|
||||
frontend/core/navigation \
|
||||
frontend/core/network \
|
||||
frontend/core/local-db \
|
||||
frontend/core/sync \
|
||||
frontend/features/auth-feature \
|
||||
frontend/features/ping-feature \
|
||||
frontend/shared \
|
||||
frontend/shells/meldestelle-portal \
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# ===================================================================
|
||||
# Multi-stage Dockerfile for Meldestelle Ping Service
|
||||
# Features: Security hardening, monitoring support, optimal caching, BuildKit cache mounts
|
||||
# Version: 2.2.0 - Optimized for Monorepo (Fixed missing frontend dirs)
|
||||
# Version: 2.2.1 - Optimized for Monorepo (Fixed frontend paths after refactoring)
|
||||
# ===================================================================
|
||||
|
||||
# === CENTRALIZED BUILD ARGUMENTS ===
|
||||
|
|
@ -53,13 +53,13 @@ COPY contracts/ contracts/
|
|||
|
||||
# Create dummy frontend directories to satisfy settings.gradle.kts include paths
|
||||
RUN mkdir -p \
|
||||
frontend/core/auth \
|
||||
frontend/core/domain \
|
||||
frontend/core/design-system \
|
||||
frontend/core/navigation \
|
||||
frontend/core/network \
|
||||
frontend/core/local-db \
|
||||
frontend/core/sync \
|
||||
frontend/features/auth-feature \
|
||||
frontend/features/ping-feature \
|
||||
frontend/shared \
|
||||
frontend/shells/meldestelle-portal \
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@
|
|||
{
|
||||
"type": "password",
|
||||
"value": "Change_Me_In_Production!",
|
||||
"temporary": true
|
||||
"temporary": false
|
||||
}
|
||||
],
|
||||
"realmRoles": [
|
||||
|
|
|
|||
|
|
@ -3,4 +3,4 @@
|
|||
Dieses Modul enthält projektübergreifende Kern-Logik und Utility-Klassen, die sowohl vom Backend als auch vom Frontend genutzt werden können.
|
||||
|
||||
**Die vollständige Dokumentation befindet sich hier:**
|
||||
[**-> docs/03_Domain/01_Core_Model/README.md**](../docs/03_Domain/01_Core_Model/README.md)
|
||||
[**→ docs/03_Domain/01_Core_Model/README.md**](../docs/03_Domain/01_Core_Model/README.md)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import at.mocode.shared.core.AppConstants
|
|||
import io.ktor.client.*
|
||||
import io.ktor.client.call.*
|
||||
import io.ktor.client.request.forms.*
|
||||
import io.ktor.client.statement.*
|
||||
import io.ktor.http.*
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
|
@ -63,9 +64,10 @@ class AuthApiClient(
|
|||
username = username
|
||||
)
|
||||
} else {
|
||||
val errorBody = response.bodyAsText()
|
||||
LoginResponse(
|
||||
success = false,
|
||||
message = "Login fehlgeschlagen: HTTP ${response.status.value}"
|
||||
message = "Login fehlgeschlagen: HTTP ${response.status.value} - $errorBody"
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
|
|
@ -104,9 +106,10 @@ class AuthApiClient(
|
|||
message = null
|
||||
)
|
||||
} else {
|
||||
val errorBody = response.bodyAsText()
|
||||
LoginResponse(
|
||||
success = false,
|
||||
message = "Token refresh fehlgeschlagen: HTTP ${response.status.value}"
|
||||
message = "Token refresh fehlgeschlagen: HTTP ${response.status.value} - $errorBody"
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ val authModule = module {
|
|||
// Single in-memory token manager
|
||||
single { AuthTokenManager() }
|
||||
|
||||
// AuthApiClient with injected apiClient and DEV client secret
|
||||
// AuthApiClient with injected baseHttpClient (NOT apiClient)
|
||||
single {
|
||||
AuthApiClient(
|
||||
httpClient = get(named("apiClient")),
|
||||
httpClient = get(named("baseHttpClient")),
|
||||
clientSecret = AppConstants.KEYCLOAK_CLIENT_SECRET
|
||||
)
|
||||
}
|
||||
|
|
@ -30,8 +30,7 @@ val authModule = module {
|
|||
single<TokenProvider> {
|
||||
object : TokenProvider {
|
||||
override fun getAccessToken(): String? {
|
||||
val token = get<AuthTokenManager>().getToken()
|
||||
return token
|
||||
return get<AuthTokenManager>().getToken()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@ package at.mocode.frontend.core.network
|
|||
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.plugins.*
|
||||
import io.ktor.client.plugins.auth.*
|
||||
import io.ktor.client.plugins.auth.providers.*
|
||||
import io.ktor.client.plugins.contentnegotiation.*
|
||||
import io.ktor.client.plugins.logging.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.serialization.kotlinx.json.*
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.koin.core.qualifier.named
|
||||
|
|
@ -19,10 +18,28 @@ interface TokenProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* Koin module that provides a preconfigured Ktor HttpClient under the named qualifier "apiClient".
|
||||
* The client uses the environment-aware base URL from NetworkConfig.
|
||||
* Koin module providing HttpClients.
|
||||
*/
|
||||
val networkModule = module {
|
||||
|
||||
// 1. Base Client (Raw, for Auth/Keycloak)
|
||||
single(named("baseHttpClient")) {
|
||||
HttpClient {
|
||||
install(ContentNegotiation) {
|
||||
json(Json { ignoreUnknownKeys = true; isLenient = true; encodeDefaults = true })
|
||||
}
|
||||
install(Logging) {
|
||||
logger = object : Logger {
|
||||
override fun log(message: String) {
|
||||
println("[baseClient] $message")
|
||||
}
|
||||
}
|
||||
level = LogLevel.INFO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. API Client (Configured for Gateway & Auth Header)
|
||||
single(named("apiClient")) {
|
||||
val tokenProvider: TokenProvider? = try { get<TokenProvider>() } catch (_: Throwable) { null }
|
||||
HttpClient {
|
||||
|
|
@ -54,19 +71,15 @@ val networkModule = module {
|
|||
exponentialDelay()
|
||||
}
|
||||
|
||||
// Authentication plugin (Bearer)
|
||||
install(Auth) {
|
||||
bearer {
|
||||
loadTokens {
|
||||
val token = tokenProvider?.getAccessToken()
|
||||
token?.let { BearerTokens(it, refreshToken = "") }
|
||||
}
|
||||
// Only send token to our API base URL
|
||||
sendWithoutRequest { request ->
|
||||
val base = NetworkConfig.baseUrl.trimEnd('/')
|
||||
val url = request.url.toString()
|
||||
url.startsWith(base)
|
||||
}
|
||||
// Manual Auth Header Injection (instead of Auth plugin) to support immediate logout
|
||||
install(DefaultRequest) {
|
||||
val base = NetworkConfig.baseUrl.trimEnd('/')
|
||||
url(base) // Set base URL
|
||||
|
||||
// Inject Authorization header if token is present
|
||||
val token = tokenProvider?.getAccessToken()
|
||||
if (token != null) {
|
||||
header("Authorization", "Bearer $token")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -79,12 +92,6 @@ val networkModule = module {
|
|||
}
|
||||
level = LogLevel.INFO
|
||||
}
|
||||
|
||||
// Set base URL
|
||||
defaultRequest {
|
||||
// Set only the base URL; endpoints will append paths
|
||||
url(NetworkConfig.baseUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user