Skip to content

Commit

Permalink
Routes: add MockRouteAccessDeniedError to the list of default error r…
Browse files Browse the repository at this point in the history
…outes
  • Loading branch information
mvysny committed Aug 1, 2024
1 parent 9dc1141 commit 55ecaab
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -220,72 +220,67 @@ internal fun DynaNodeGroup.navigatorTest() {
}

group("security") {
group("no user logged in") {
test("both mock routes are present") {
expect(true, routes.toString()) { routes.errorRoutes.contains(MockRouteNotFoundError::class.java) }
expect(true, routes.toString()) { routes.errorRoutes.contains(MockRouteAccessDeniedError::class.java) }
}
test("when access is rejected, redirect goes to WelcomeView") {
UI.getCurrent().addBeforeEnterListener(SimpleNavigationAccessControl().apply {
setLoginView(WelcomeView::class.java)
})
navigateTo<TestingView>()
expectView<WelcomeView>()
navigatorSecurityTests("com.github") // includes also Karibu-Testing MockRouteNotFoundError and MockRouteAccessDeniedError on classpath
navigatorSecurityTests(null) // includes everything on classpath, including Flow's default RouteNotFoundError and RouteAccessDeniedError and also MyRouteNotFoundError
navigatorSecurityTests("test.app") // includes only MyRouteNotFoundError, but not Mock*Errors nor Flow default routes.
navigatorSecurityTests("nonexisting.pkg") // includes nothing.
}
}

@Route("navigation-postpone")
class NavigationPostponeView : VerticalLayout(), BeforeLeaveObserver {
override fun beforeLeave(event: BeforeLeaveEvent) {
val action = event.postpone()
Dialog().apply {
span("Are you sure you want to leave such a beautiful view?")
button("Yes") {
onLeftClick { action.proceed(); close() }
}
test("when access is rejected and no login view is set, redirects to MockRouteNotFoundError") {
UI.getCurrent().addBeforeEnterListener(SimpleNavigationAccessControl())
expectThrows<NotFoundException>("No route found for 'testing': Consider adding one of the following annotations to make the view accessible: @AnonymousAllowed, @PermitAll, @RolesAllowed.") {
navigateTo<TestingView>()
}
button("No") {
onLeftClick { close() }
}
}
group("user logged in") {
test("when access is rejected, default handler redirects to MockRouteNotFoundError") {
MockVaadin.tearDown()
val routes = Routes().autoDiscoverViews("com.github")
routes.errorRoutes.remove(MockRouteAccessDeniedError::class.java)
MockVaadin.setup(routes)
}.open()
}
}

UI.getCurrent().addBeforeEnterListener(SimpleNavigationAccessControl("admin"))
expectThrows<NotFoundException>("No route found for 'testing': Consider adding one of the following annotations to make the view accessible: @AnonymousAllowed, @PermitAll, @RolesAllowed.") {
navigateTo<TestingView>()
}
}
test("when access is rejected, Karibu's MockRouteAccessDeniedError throws AccessDeniedException") {
UI.getCurrent().addBeforeEnterListener(SimpleNavigationAccessControl("admin"))
expectThrows<AccessDeniedException>("Consider adding one of the following annotations to make the view accessible: @AnonymousAllowed, @PermitAll, @RolesAllowed") {
navigateTo<TestingView>()
}
class SimpleNavigationAccessControl(val user: String? = null) : NavigationAccessControl() {
override fun getPrincipal(request: VaadinRequest?): Principal? = if (user == null) null else SimplePrincipal(user)
override fun getRolesChecker(request: VaadinRequest?): Predicate<String> = Predicate { false }
}

data class SimplePrincipal(private val name: String): Principal, Serializable {
override fun getName(): String = name
}

@DynaTestDsl
internal fun DynaNodeGroup.navigatorSecurityTests(classpathScanPackage: String?) {
group("classpath scan of $classpathScanPackage") {
lateinit var routes: Routes
beforeEach {
MockVaadin.tearDown()
routes = Routes().autoDiscoverViews(classpathScanPackage)
if (routes.errorRoutes.contains(MyRouteNotFoundError::class.java)) {
routes.errorRoutes.remove(MyRouteNotFoundError::class.java)
routes.errorRoutes.add(MockRouteNotFoundError::class.java)
}
routes.routes.addAll(setOf(TestingView::class.java, WelcomeView::class.java))
MockVaadin.setup(routes)
}
}
group("security2 - with all routes") {
beforeEach { MockVaadin.tearDown() }
afterEach { MockVaadin.tearDown() }

group("no user logged in") {
test("both mock routes are present") {
val routes = Routes().autoDiscoverViews()
expect(true, routes.toString()) { routes.errorRoutes.contains(MockRouteNotFoundError::class.java) }
expect(true, routes.toString()) { routes.errorRoutes.contains(MockRouteAccessDeniedError::class.java) }
}
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<TestingView>()
expectView<WelcomeView>()
}
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<NotFoundException>("No route found for 'testing': Consider adding one of the following annotations to make the view accessible: @AnonymousAllowed, @PermitAll, @RolesAllowed.") {
navigateTo<TestingView>()
Expand All @@ -294,9 +289,7 @@ internal fun DynaNodeGroup.navigatorTest() {
}
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)
MockVaadin.tearDown()
routes.errorRoutes.remove(MockRouteAccessDeniedError::class.java)
MockVaadin.setup(routes)

Expand All @@ -306,11 +299,6 @@ internal fun DynaNodeGroup.navigatorTest() {
}
}
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<AccessDeniedException>("Consider adding one of the following annotations to make the view accessible: @AnonymousAllowed, @PermitAll, @RolesAllowed") {
navigateTo<TestingView>()
Expand All @@ -319,28 +307,3 @@ internal fun DynaNodeGroup.navigatorTest() {
}
}
}

@Route("navigation-postpone")
class NavigationPostponeView : VerticalLayout(), BeforeLeaveObserver {
override fun beforeLeave(event: BeforeLeaveEvent) {
val action = event.postpone()
Dialog().apply {
span("Are you sure you want to leave such a beautiful view?")
button("Yes") {
onLeftClick { action.proceed(); close() }
}
button("No") {
onLeftClick { close() }
}
}.open()
}
}

class SimpleNavigationAccessControl(val user: String? = null) : NavigationAccessControl() {
override fun getPrincipal(request: VaadinRequest?): Principal? = if (user == null) null else SimplePrincipal(user)
override fun getRolesChecker(request: VaadinRequest?): Predicate<String> = Predicate { false }
}

data class SimplePrincipal(private val name: String): Principal, Serializable {
override fun getName(): String = name
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import kotlin.test.expect
*/
public data class Routes(
val routes: MutableSet<Class<out Component>> = mutableSetOf(),
val errorRoutes: MutableSet<Class<out HasErrorParameter<*>>> = mutableSetOf(MockRouteNotFoundError::class.java),
val errorRoutes: MutableSet<Class<out HasErrorParameter<*>>> = mutableSetOf(MockRouteNotFoundError::class.java, MockRouteAccessDeniedError::class.java),
var skipPwaInit: Boolean = true
) : Serializable {

Expand Down

0 comments on commit 55ecaab

Please sign in to comment.