feat(MP-29): navigation core module, auth guards & shell wiring\n\n- Establish :frontend:core:navigation module with DeepLinkHandler\n- Introduce NavigationPort & CurrentUserProvider (DI)\n- Harden admin routes against AppRoles.ADMIN\n- Wire Koin in JS/JVM/Wasm shells (navigationModule)\n- Remove legacy DeepLinkHandler from shared\n- Add unit tests for guard logic\n\nRef: MP-29 (#24)

This commit is contained in:
StefanMo
2025-12-08 14:23:08 +01:00
committed by GitHub
parent df2562ea23
commit 5ea4730cd4
14 changed files with 283 additions and 236 deletions
@@ -0,0 +1,39 @@
package navigation
import at.mocode.clients.authfeature.AuthTokenManager
import at.mocode.frontend.core.domain.models.User
import at.mocode.frontend.core.navigation.CurrentUserProvider
import at.mocode.frontend.core.navigation.DeepLinkHandler
import at.mocode.frontend.core.navigation.NavigationPort
import org.koin.dsl.module
class ShellCurrentUserProvider(
private val authTokenManager: AuthTokenManager,
) : CurrentUserProvider {
override fun getCurrentUser(): User? {
val state = authTokenManager.authState.value
if (!state.isAuthenticated) return null
// Roles are not yet modeled in AuthState; provide empty list for now
return User(
id = state.userId ?: state.username ?: "unknown",
username = state.username ?: state.userId ?: "unknown",
displayName = null,
roles = emptyList(),
)
}
}
class NoopNavigationPort : NavigationPort {
var lastRoute: String? = null
override fun navigateTo(route: String) {
lastRoute = route
// Simple logging; actual routing is handled elsewhere in the shell
println("[NavigationPort] navigateTo $route")
}
}
val navigationModule = module {
single<CurrentUserProvider> { ShellCurrentUserProvider(get()) }
single<NavigationPort> { NoopNavigationPort() }
single { DeepLinkHandler(get(), get()) }
}
@@ -7,6 +7,7 @@ import at.mocode.frontend.core.network.networkModule
import at.mocode.clients.authfeature.di.authFeatureModule
import at.mocode.frontend.core.localdb.localDbModule
import at.mocode.frontend.core.localdb.DatabaseProvider
import navigation.navigationModule
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import org.koin.core.context.GlobalContext
@@ -20,8 +21,8 @@ fun main() {
console.log("[WebApp] main() entered")
// Initialize DI (Koin) with shared modules + network + local DB modules
try {
initKoin { modules(networkModule, localDbModule, authFeatureModule) }
console.log("[WebApp] Koin initialized with networkModule + localDbModule + authFeatureModule")
initKoin { modules(networkModule, localDbModule, authFeatureModule, navigationModule) }
console.log("[WebApp] Koin initialized with networkModule + localDbModule + authFeatureModule + navigationModule")
} catch (e: dynamic) {
console.warn("[WebApp] Koin initialization warning:", e)
}
@@ -5,12 +5,13 @@ import androidx.compose.ui.unit.dp
import at.mocode.shared.di.initKoin
import at.mocode.frontend.core.network.networkModule
import at.mocode.clients.authfeature.di.authFeatureModule
import navigation.navigationModule
fun main() = application {
// Initialize DI (Koin) with shared modules + network module
try {
initKoin { modules(networkModule, authFeatureModule) }
println("[DesktopApp] Koin initialized with networkModule + authFeatureModule")
initKoin { modules(networkModule, authFeatureModule, navigationModule) }
println("[DesktopApp] Koin initialized with networkModule + authFeatureModule + navigationModule")
} catch (e: Exception) {
println("[DesktopApp] Koin initialization warning: ${e.message}")
}
@@ -6,13 +6,14 @@ import org.w3c.dom.HTMLElement
import at.mocode.shared.di.initKoin
import at.mocode.frontend.core.network.networkModule
import at.mocode.clients.authfeature.di.authFeatureModule
import navigation.navigationModule
@OptIn(ExperimentalComposeUiApi::class)
fun main() {
// Initialize DI
try {
initKoin { modules(networkModule, authFeatureModule) }
println("[WasmApp] Koin initialized")
initKoin { modules(networkModule, authFeatureModule, navigationModule) }
println("[WasmApp] Koin initialized (with navigationModule)")
} catch (e: Exception) {
println("[WasmApp] Koin init failed: ${e.message}")
}