From c5f6b18cd33ee30f3db710b6ad4ee72648d3998d Mon Sep 17 00:00:00 2001 From: Simon Bruder Date: Thu, 7 Dec 2023 19:53:05 +0100 Subject: [PATCH] Make inventory authorization tests more complete --- .../InventoryControllerIntegrationTests.java | 103 +++++++++++++++--- 1 file changed, 86 insertions(+), 17 deletions(-) diff --git a/src/test/java/catering/inventory/InventoryControllerIntegrationTests.java b/src/test/java/catering/inventory/InventoryControllerIntegrationTests.java index 68493d8..202793c 100644 --- a/src/test/java/catering/inventory/InventoryControllerIntegrationTests.java +++ b/src/test/java/catering/inventory/InventoryControllerIntegrationTests.java @@ -16,12 +16,18 @@ */ package catering.inventory; +import static catering.inventory.InventoryControllerIntegrationTests.PermissionResult.FORBIDDEN; +import static catering.inventory.InventoryControllerIntegrationTests.PermissionResult.LOGIN; +import static catering.inventory.InventoryControllerIntegrationTests.PermissionResult.OK; +import static catering.inventory.InventoryControllerIntegrationTests.PermissionResult.OVERVIEW; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.endsWith; import static org.hamcrest.CoreMatchers.not; import static org.salespointframework.core.Currencies.EURO; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.anonymous; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; @@ -47,8 +53,10 @@ import org.springframework.http.HttpHeaders; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import catering.catalog.Consumable; +import catering.catalog.Rentable; import catering.order.OrderType; @AutoConfigureMockMvc @@ -206,6 +214,43 @@ class InventoryControllerIntegrationTests { .andExpect(content().string(containsString("Ungültiger Name"))); } + /* + * Tests for authorization + */ + + static enum PermissionResult { + /** + * The result is an HTTP 403 (Forbidden) error code + */ + FORBIDDEN, + /** + * The result is a redirect to the login page + */ + LOGIN, + /** + * The result is an HTTP 200 (Ok) status code + */ + OK, + /** + * The result is a redirect to the inventory overview page + */ + OVERVIEW; + + @FunctionalInterface + public interface PermissionChecker { + ResultActions check(ResultActions resultActions) throws Exception; + } + + PermissionChecker toChecker() { + return switch (this) { + case FORBIDDEN -> ra -> ra.andExpect(status().isForbidden()); + case LOGIN -> InventoryControllerIntegrationTests::assertRedirectsToLogin; + case OK -> ra -> ra.andExpect(status().isOk()); + case OVERVIEW -> ra -> ra.andExpect(redirectedUrl("/inventory")); + }; + } + } + /** * Helper function for asserting that protected endpoints are not accessible by * unauthentificated users. @@ -215,7 +260,7 @@ class InventoryControllerIntegrationTests { * @return the {@link ResultActions} given as a parameter to perform more * matching on */ - ResultActions assertRedirectsToLogin(ResultActions resultActions) throws Exception { + static ResultActions assertRedirectsToLogin(ResultActions resultActions) throws Exception { // Spring security uses the full URL to redirect to login, // so we can’t use redirectedUrl("/login") in this case. return resultActions @@ -223,36 +268,60 @@ class InventoryControllerIntegrationTests { .andExpect(header().string(HttpHeaders.LOCATION, endsWith("/login"))); } - @Test - void disallowUnauthorizedList() throws Exception { - assertRedirectsToLogin(mvc.perform(get("/inventory"))); + ResultActions requestAsAnonymous(MockHttpServletRequestBuilder requestBuilder) throws Exception { + return mvc.perform(requestBuilder.with(anonymous())); + } + + ResultActions requestAsCustomer(MockHttpServletRequestBuilder requestBuilder) throws Exception { + return mvc.perform(requestBuilder.with(user("unprivileged").roles("CUSTOMER"))); + } + + ResultActions requestAsAdministrator(MockHttpServletRequestBuilder requestBuilder) throws Exception { + return mvc.perform(requestBuilder.with(user("admin").roles("ADMIN"))); + } + + void checkPermissions(MockHttpServletRequestBuilder requestBuilder, PermissionResult anonymous, + PermissionResult customer, PermissionResult administrator) throws Exception { + anonymous.toChecker().check(requestAsAnonymous(requestBuilder)); + customer.toChecker().check(requestAsCustomer(requestBuilder)); + administrator.toChecker().check(requestAsAdministrator(requestBuilder)); } @Test - void disallowUnauthorizedEditPage() throws Exception { - assertRedirectsToLogin( - mvc.perform(get("/inventory/edit/" + anyPid).queryParam("type", Consumable.class.getSimpleName()))); + void checkPermissionsForList() throws Exception { + checkPermissions(get("/inventory"), LOGIN, FORBIDDEN, OK); } @Test - void disallowUnauthorizedEdit() throws Exception { - assertRedirectsToLogin( - mvc.perform(post("/inventory/edit/" + anyPid).queryParam("type", Consumable.class.getSimpleName()))); + void checkPermissionsForEditPage() throws Exception { + for (Class type : Set.of(Consumable.class, Rentable.class)) { + checkPermissions(get("/inventory/edit/" + anyPid).queryParam("type", type.getSimpleName()), + LOGIN, FORBIDDEN, OK); + } } @Test - void disallowUnauthorizedAddPage() throws Exception { - assertRedirectsToLogin(mvc.perform(get("/inventory/add").queryParam("type", Consumable.class.getSimpleName()))); + void checkPermissionsForEdit() throws Exception { + for (Class type : Set.of(Consumable.class, Rentable.class)) { + checkPermissions(post("/inventory/edit/" + anyPid).queryParam("type", type.getSimpleName()), + LOGIN, FORBIDDEN, OK); + } } @Test - void disallowUnauthorizedAdd() throws Exception { - assertRedirectsToLogin( - mvc.perform(post("/inventory/add").queryParam("type", Consumable.class.getSimpleName()))); + void checkPermissionsForAddPage() throws Exception { + checkPermissions(get("/inventory/add").queryParam("type", Consumable.class.getSimpleName()), LOGIN, FORBIDDEN, + OK); } @Test - void disallowUnauthorizedDelete() throws Exception { - assertRedirectsToLogin(mvc.perform(get("/inventory/delete/" + anyPid))); + void checkPermissionsForAdd() throws Exception { + checkPermissions(post("/inventory/add").queryParam("type", Consumable.class.getSimpleName()), LOGIN, FORBIDDEN, + OK); + } + + @Test + void checkPermissionsForDelete() throws Exception { + checkPermissions(get("/inventory/delete/" + anyPid), LOGIN, FORBIDDEN, OVERVIEW); } }