Skip to content

Commit

Permalink
fix nullpointer on navigation access check
Browse files Browse the repository at this point in the history
  • Loading branch information
F43nd1r committed Dec 15, 2024
1 parent 3f408dd commit b4d89a4
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 30 deletions.
35 changes: 23 additions & 12 deletions acrarium/src/main/kotlin/com/faendir/acra/navigation/RouteParams.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* (C) Copyright 2022-2023 Lukas Morawietz (https://github.com/F43nd1r)
* (C) Copyright 2022-2024 Lukas Morawietz (https://github.com/F43nd1r)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -30,29 +30,40 @@ import org.springframework.stereotype.Component

@Component
@ListenerPriority(1000)
class RouteParams : UIInitListener, BeforeEnterListener {
private val cache = mutableMapOf<Int, RouteParameters>()
class RouteParams(private val cache: MutableMap<Int, RouteParameters> = mutableMapOf()) : UIInitListener, BeforeEnterListener, RouteParameterProvider by RouteParameterParser({
cache[UI.getCurrent()?.uiId ?: throw IllegalStateException("No UI present")] ?: throw IllegalStateException("No cache entry for UI present")
}) {

override fun uiInit(uiInitEvent: UIInitEvent) {
uiInitEvent.ui.addBeforeEnterListener(this)
}

override fun beforeEnter(event: BeforeEnterEvent) {
cache[event.ui.uiId] = event.routeParameters
}
}

fun appId(): AppId = AppId(parse(PARAM_APP) { it.toInt() })
interface RouteParameterProvider {
fun appId(): AppId
fun bugId(): BugId
fun reportId(): String
fun installationId(): String
}

fun bugId(): BugId = BugId(parse(PARAM_BUG) { it.toInt() })
class RouteParameterParser(private val getRouteParameters: () -> RouteParameters) : RouteParameterProvider {
private fun <T> parse(param: String, parse: (String) -> T?): T {
val value = getRouteParameters().get(param)?.toNullable() ?: throw IllegalArgumentException("Parameter $param not present")
return parse(value) ?: throw IllegalArgumentException("Parse failure for parameter $param")
}

fun reportId(): String = parse(PARAM_REPORT) { it }
override fun appId(): AppId = AppId(parse(PARAM_APP) { it.toInt() })

fun installationId(): String = parse(PARAM_INSTALLATION) { it }
override fun bugId(): BugId = BugId(parse(PARAM_BUG) { it.toInt() })

override fun reportId(): String = parse(PARAM_REPORT) { it }

override fun installationId(): String = parse(PARAM_INSTALLATION) { it }

fun <T> parse(param: String, parse: (String) -> T?): T {
val id = UI.getCurrent()?.uiId ?: throw IllegalStateException("No UI present")
val value = cache[id]?.get(param)?.toNullable() ?: throw IllegalArgumentException("Parameter $param not present")
return parse(value) ?: throw IllegalArgumentException("Parse failure for parameter $param")
}
}

const val PARAM_APP = "app"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* (C) Copyright 2022 Lukas Morawietz (https://github.com/F43nd1r)
* (C) Copyright 2022-2024 Lukas Morawietz (https://github.com/F43nd1r)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,20 +15,29 @@
*/
package com.faendir.acra.security

import com.faendir.acra.navigation.RouteParams
import com.vaadin.flow.server.auth.AccessAnnotationChecker
import org.springframework.stereotype.Component
import java.lang.reflect.Method
import java.security.Principal
import java.util.function.Function
import com.faendir.acra.navigation.RouteParameterParser
import com.vaadin.flow.server.auth.AccessCheckResult
import com.vaadin.flow.server.auth.NavigationAccessChecker
import com.vaadin.flow.server.auth.NavigationContext
import com.vaadin.flow.spring.security.NavigationAccessControlConfigurer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Component
class AcrariumAccessAnnotationChecker(private val routeParams: RouteParams) : AccessAnnotationChecker() {
override fun hasAccess(method: Method, principal: Principal?, roleChecker: Function<String, Boolean>): Boolean {
return SecurityUtils.hasAccess(routeParams::appId, method.declaringClass) || super.hasAccess(method, principal, roleChecker)
}
@Configuration
class AcrariumAccessAnnotationConfiguration {
@Bean
fun navigationAccessControlConfigurerCustomizer(): NavigationAccessControlConfigurer =
NavigationAccessControlConfigurer().withNavigationAccessChecker(AcrariumAccessAnnotationChecker())
}

override fun hasAccess(cls: Class<*>, principal: Principal?, roleChecker: Function<String, Boolean>): Boolean {
return SecurityUtils.hasAccess(routeParams::appId, cls) || super.hasAccess(cls, principal, roleChecker)
class AcrariumAccessAnnotationChecker : NavigationAccessChecker {
override fun check(context: NavigationContext): AccessCheckResult {
val parameters = RouteParameterParser { context.parameters }
return if (SecurityUtils.hasAccess(parameters::appId, context.navigationTarget)) {
AccessCheckResult.allow()
} else {
val appId = runCatching { parameters.appId() }.getOrNull()
AccessCheckResult.deny("User ${context.principal} does not have access to ${context.navigationTarget}${appId?.let { " for app $it" }}")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector
@EnableWebSecurity
@Import(SpringSecurityAutoConfiguration::class)
class WebSecurityConfiguration(private val userRepository: UserRepository) : VaadinWebSecurity() {


@Bean(name = [BeanIds.AUTHENTICATION_MANAGER])
fun authenticationManager(http: HttpSecurity): AuthenticationManager =
http.getSharedObject(AuthenticationManagerBuilder::class.java)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* (C) Copyright 2020-2023 Lukas Morawietz (https://github.com/F43nd1r)
* (C) Copyright 2020-2024 Lukas Morawietz (https://github.com/F43nd1r)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -51,7 +51,6 @@ import kotlin.math.max
@Route(value = "app/:$PARAM_APP/bug/:$PARAM_BUG/report/:$PARAM_REPORT", layout = MainView::class)
@LogicalParent(ReportBugTab::class)
@RequiresPermission(Permission.Level.VIEW)
@RequiresPermission(Permission.Level.VIEW)
class ReportView(
private val reportRepository: ReportRepository,
versionRepository: VersionRepository,
Expand Down

0 comments on commit b4d89a4

Please sign in to comment.