From 47c9bf868a408d37f8960a8f858e7ecf06f2c39c Mon Sep 17 00:00:00 2001 From: Martin Vysny Date: Thu, 1 Aug 2024 10:47:21 +0300 Subject: [PATCH] Routes.kt: drop Vaadin @DefaultHandlers for RouteNotFoundError and AccessDeniedError --- .../mvysny/kaributesting/v10/NavigatorTest.kt | 56 +++++++++++++++++++ .../mvysny/kaributesting/v10/RoutesTest.kt | 6 +- .../github/mvysny/kaributesting/v10/Routes.kt | 8 +++ 3 files changed, 65 insertions(+), 5 deletions(-) diff --git a/karibu-testing-v10/kt10-tests/src/main/kotlin/com/github/mvysny/kaributesting/v10/NavigatorTest.kt b/karibu-testing-v10/kt10-tests/src/main/kotlin/com/github/mvysny/kaributesting/v10/NavigatorTest.kt index 241fbb7e..eb68d8e8 100644 --- a/karibu-testing-v10/kt10-tests/src/main/kotlin/com/github/mvysny/kaributesting/v10/NavigatorTest.kt +++ b/karibu-testing-v10/kt10-tests/src/main/kotlin/com/github/mvysny/kaributesting/v10/NavigatorTest.kt @@ -21,6 +21,7 @@ import com.vaadin.flow.router.Route import com.vaadin.flow.router.RouteNotFoundError import com.vaadin.flow.server.VaadinRequest import com.vaadin.flow.server.auth.NavigationAccessControl +import test.app.MyRouteNotFoundError import java.io.Serializable import java.security.Principal import java.util.function.Predicate @@ -254,6 +255,61 @@ internal fun DynaNodeGroup.navigatorTest() { } } } + group("security2 - with all routes") { + beforeEach { MockVaadin.tearDown() } + afterEach { MockVaadin.tearDown() } + + group("no user logged in") { + test("when access is rejected, redirect goes to WelcomeView") { + val routes = Routes().autoDiscoverViews() + routes.errorRoutes.remove(MyRouteNotFoundError::class.java) + routes.errorRoutes.add(MockRouteNotFoundError::class.java) + MockVaadin.setup(routes) + + UI.getCurrent().addBeforeEnterListener(SimpleNavigationAccessControl().apply { + setLoginView(WelcomeView::class.java) + }) + navigateTo() + expectView() + } + test("when access is rejected and no login view is set, redirects to MockRouteNotFoundError") { + val routes = Routes().autoDiscoverViews() + routes.errorRoutes.remove(MyRouteNotFoundError::class.java) + routes.errorRoutes.add(MockRouteNotFoundError::class.java) + MockVaadin.setup(routes) + + UI.getCurrent().addBeforeEnterListener(SimpleNavigationAccessControl()) + expectThrows("No route found for 'testing': Consider adding one of the following annotations to make the view accessible: @AnonymousAllowed, @PermitAll, @RolesAllowed.") { + navigateTo() + } + } + } + group("user logged in") { + test("when access is rejected, default handler redirects to MockRouteNotFoundError") { + val routes = Routes().autoDiscoverViews() + routes.errorRoutes.remove(MyRouteNotFoundError::class.java) + routes.errorRoutes.add(MockRouteNotFoundError::class.java) + routes.errorRoutes.remove(MockRouteAccessDeniedError::class.java) + MockVaadin.setup(routes) + + UI.getCurrent().addBeforeEnterListener(SimpleNavigationAccessControl("admin")) + expectThrows("No route found for 'testing': Consider adding one of the following annotations to make the view accessible: @AnonymousAllowed, @PermitAll, @RolesAllowed.") { + navigateTo() + } + } + test("when access is rejected, Karibu's MockRouteAccessDeniedError throws AccessDeniedException") { + val routes = Routes().autoDiscoverViews() + routes.errorRoutes.remove(MyRouteNotFoundError::class.java) + routes.errorRoutes.add(MockRouteNotFoundError::class.java) + MockVaadin.setup(routes) + + UI.getCurrent().addBeforeEnterListener(SimpleNavigationAccessControl("admin")) + expectThrows("Consider adding one of the following annotations to make the view accessible: @AnonymousAllowed, @PermitAll, @RolesAllowed") { + navigateTo() + } + } + } + } } @Route("navigation-postpone") diff --git a/karibu-testing-v10/kt10-tests/src/main/kotlin/com/github/mvysny/kaributesting/v10/RoutesTest.kt b/karibu-testing-v10/kt10-tests/src/main/kotlin/com/github/mvysny/kaributesting/v10/RoutesTest.kt index cc2a5d35..625d685f 100644 --- a/karibu-testing-v10/kt10-tests/src/main/kotlin/com/github/mvysny/kaributesting/v10/RoutesTest.kt +++ b/karibu-testing-v10/kt10-tests/src/main/kotlin/com/github/mvysny/kaributesting/v10/RoutesTest.kt @@ -49,11 +49,7 @@ fun DynaNodeGroup.routesTestBatch() { // https://github.com/mvysny/karibu-testing/issues/50 test("app-specific NotFoundException handler removes MockRouteNotFoundError") { val routes: Routes = Routes().autoDiscoverViews() - // Vaadin 24.3+ introduces additional route - val routeAccessDeniedError = if (VaadinVersion.get.isAtLeast(24, 3)) Class.forName("com.vaadin.flow.router.RouteAccessDeniedError") else null - val expectedRouteClasses = - setOf(ErrorView::class.java, InternalServerError::class.java, MyRouteNotFoundError::class.java, RouteNotFoundError::class.java, routeAccessDeniedError) - .filterNotNull().toSet() + val expectedRouteClasses = setOf(ErrorView::class.java, InternalServerError::class.java, MyRouteNotFoundError::class.java, MockRouteAccessDeniedError::class.java) expect(expectedRouteClasses) { routes.errorRoutes.toSet() } // make sure that Vaadin initializes properly with this set of views MockVaadin.setup(routes) diff --git a/karibu-testing-v10/src/main/kotlin/com/github/mvysny/kaributesting/v10/Routes.kt b/karibu-testing-v10/src/main/kotlin/com/github/mvysny/kaributesting/v10/Routes.kt index a69daa59..1db302a0 100644 --- a/karibu-testing-v10/src/main/kotlin/com/github/mvysny/kaributesting/v10/Routes.kt +++ b/karibu-testing-v10/src/main/kotlin/com/github/mvysny/kaributesting/v10/Routes.kt @@ -1,6 +1,7 @@ package com.github.mvysny.kaributesting.v10 import com.github.mvysny.kaributesting.v10.mock.MockVaadin19 +import com.github.mvysny.kaributools.VaadinVersion import com.vaadin.flow.component.Component import com.vaadin.flow.component.Tag import com.vaadin.flow.router.* @@ -83,6 +84,13 @@ public data class Routes( } } + // remove @DefaultErrorHandler RouteAccessDeniedError and RouteNotFoundError so that they're replaced with Karibu's Mock counterparts + // which perform better logging + errorRoutes.remove(RouteNotFoundError::class.java) + if (VaadinVersion.get.isAtLeast(24, 3)) { + errorRoutes.remove(Class.forName("com.vaadin.flow.router.RouteAccessDeniedError")) + } + // https://github.com/mvysny/karibu-testing/issues/50 // if the app defines its own NotFoundException handler, remove MockRouteNotFoundError if (errorRoutes.any { it != MockRouteNotFoundError::class.java && it.isRouteNotFound }) {