Make inventory authorization tests more complete

This commit is contained in:
Simon Bruder 2023-12-07 19:53:05 +01:00
parent 0eb3276dde
commit c5f6b18cd3
Signed by: simon
GPG key ID: 8D3C82F9F309F8EC

View file

@ -16,12 +16,18 @@
*/ */
package catering.inventory; 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.assertThat;
import static org.assertj.core.api.Assertions.tuple; import static org.assertj.core.api.Assertions.tuple;
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.endsWith; import static org.hamcrest.CoreMatchers.endsWith;
import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.not;
import static org.salespointframework.core.Currencies.EURO; 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.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 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.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import catering.catalog.Consumable; import catering.catalog.Consumable;
import catering.catalog.Rentable;
import catering.order.OrderType; import catering.order.OrderType;
@AutoConfigureMockMvc @AutoConfigureMockMvc
@ -206,6 +214,43 @@ class InventoryControllerIntegrationTests {
.andExpect(content().string(containsString("Ungültiger Name"))); .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 * Helper function for asserting that protected endpoints are not accessible by
* unauthentificated users. * unauthentificated users.
@ -215,7 +260,7 @@ class InventoryControllerIntegrationTests {
* @return the {@link ResultActions} given as a parameter to perform more * @return the {@link ResultActions} given as a parameter to perform more
* matching on * 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, // Spring security uses the full URL to redirect to login,
// so we cant use redirectedUrl("/login") in this case. // so we cant use redirectedUrl("/login") in this case.
return resultActions return resultActions
@ -223,36 +268,60 @@ class InventoryControllerIntegrationTests {
.andExpect(header().string(HttpHeaders.LOCATION, endsWith("/login"))); .andExpect(header().string(HttpHeaders.LOCATION, endsWith("/login")));
} }
@Test ResultActions requestAsAnonymous(MockHttpServletRequestBuilder requestBuilder) throws Exception {
void disallowUnauthorizedList() throws Exception { return mvc.perform(requestBuilder.with(anonymous()));
assertRedirectsToLogin(mvc.perform(get("/inventory"))); }
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 @Test
void disallowUnauthorizedEditPage() throws Exception { void checkPermissionsForList() throws Exception {
assertRedirectsToLogin( checkPermissions(get("/inventory"), LOGIN, FORBIDDEN, OK);
mvc.perform(get("/inventory/edit/" + anyPid).queryParam("type", Consumable.class.getSimpleName())));
} }
@Test @Test
void disallowUnauthorizedEdit() throws Exception { void checkPermissionsForEditPage() throws Exception {
assertRedirectsToLogin( for (Class<? extends Product> type : Set.of(Consumable.class, Rentable.class)) {
mvc.perform(post("/inventory/edit/" + anyPid).queryParam("type", Consumable.class.getSimpleName()))); checkPermissions(get("/inventory/edit/" + anyPid).queryParam("type", type.getSimpleName()),
LOGIN, FORBIDDEN, OK);
}
} }
@Test @Test
void disallowUnauthorizedAddPage() throws Exception { void checkPermissionsForEdit() throws Exception {
assertRedirectsToLogin(mvc.perform(get("/inventory/add").queryParam("type", Consumable.class.getSimpleName()))); for (Class<? extends Product> type : Set.of(Consumable.class, Rentable.class)) {
checkPermissions(post("/inventory/edit/" + anyPid).queryParam("type", type.getSimpleName()),
LOGIN, FORBIDDEN, OK);
}
} }
@Test @Test
void disallowUnauthorizedAdd() throws Exception { void checkPermissionsForAddPage() throws Exception {
assertRedirectsToLogin( checkPermissions(get("/inventory/add").queryParam("type", Consumable.class.getSimpleName()), LOGIN, FORBIDDEN,
mvc.perform(post("/inventory/add").queryParam("type", Consumable.class.getSimpleName()))); OK);
} }
@Test @Test
void disallowUnauthorizedDelete() throws Exception { void checkPermissionsForAdd() throws Exception {
assertRedirectsToLogin(mvc.perform(get("/inventory/delete/" + anyPid))); 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);
} }
} }