Skip to content

Commit

Permalink
Fix onboarding single namespace and improve response http codes for e…
Browse files Browse the repository at this point in the history
…xceptions (InseeFrLab#245)
  • Loading branch information
johnksv committed Aug 3, 2023
1 parent 4120cc6 commit 777a0af
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package fr.insee.onyxia.api.controller;

import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class RestExceptionHandler {

@ResponseStatus(value = HttpStatus.FORBIDDEN)
@ExceptionHandler(AccessDeniedException.class)
public void handleAccessDeniedException(Exception ignored) {}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package fr.insee.onyxia.api.controller.api.onboarding;

import fr.insee.onyxia.api.controller.exception.NamespaceAlreadyExistException;
import fr.insee.onyxia.api.controller.exception.OnboardingDisabledException;
import fr.insee.onyxia.api.services.UserProvider;
import fr.insee.onyxia.api.services.impl.kubernetes.KubernetesService;
Expand Down Expand Up @@ -43,9 +44,13 @@ public class OnboardingController {
@PostMapping
public void onboard(
@Parameter(hidden = true) Region region, @RequestBody OnboardingRequest request) {
if (region.getServices().isSingleNamespace()) {
throw new NamespaceAlreadyExistException();
}
if (!region.getServices().isAllowNamespaceCreation()) {
throw new OnboardingDisabledException();
}

checkPermissions(region, request);
final KubernetesService.Owner owner = new KubernetesService.Owner();
if (request.getGroup() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value = HttpStatus.NOT_IMPLEMENTED)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public class OnboardingDisabledException extends RuntimeException {
public OnboardingDisabledException() {
super("Onboarding is disabled on this onyxia instance");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package fr.insee.onyxia.api.controller.api.onboarding;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.fasterxml.jackson.databind.ObjectMapper;
import fr.insee.onyxia.api.configuration.BaseTest;
import fr.insee.onyxia.api.configuration.SecurityConfig;
import fr.insee.onyxia.api.configuration.properties.RegionsConfiguration;
import fr.insee.onyxia.api.controller.exception.NamespaceAlreadyExistException;
import fr.insee.onyxia.api.services.UserProvider;
import fr.insee.onyxia.api.services.impl.kubernetes.KubernetesService;
import fr.insee.onyxia.api.services.utils.HttpRequestUtils;
import fr.insee.onyxia.api.user.OnyxiaUserProvider;
import fr.insee.onyxia.model.User;
import fr.insee.onyxia.model.region.Region;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;

@WebMvcTest(OnboardingController.class)
class OnboardingControllerTest extends BaseTest {

@Autowired private MockMvc mockMvc;
@Autowired private ObjectMapper mapper;

@MockBean private UserProvider userProvider;
@MockBean private RegionsConfiguration regionsConfiguration;

@MockBean private HttpRequestUtils httpRequestUtils;
@MockBean private SecurityConfig securityConfig;
@MockBean private OnyxiaUserProvider onyxiaUserProvider;
@MockBean private KubernetesService kubernetesService;

@Test
public void should_not_create_namespace_when_single_project() throws Exception {
Region region = new Region();
Region.Services servicesConfiguration = new Region.Services();
servicesConfiguration.setSingleNamespace(true);
region.setServices(servicesConfiguration);
when(regionsConfiguration.getDefaultRegion()).thenReturn(region);
mockMvc.perform(post("/onboarding").content("{}").contentType(APPLICATION_JSON))
.andExpect(status().isConflict());
}

@Test
public void should_not_create_namespace_when_allow_namespace_creation_is_false()
throws Exception {
Region region = new Region();
Region.Services servicesConfiguration = new Region.Services();
servicesConfiguration.setSingleNamespace(false);
servicesConfiguration.setAllowNamespaceCreation(false);
region.setServices(servicesConfiguration);
when(regionsConfiguration.getDefaultRegion()).thenReturn(region);
when(userProvider.getUser(any())).thenReturn(User.newInstance().setIdep("default").build());

mockMvc.perform(post("/onboarding").content("{}").contentType(APPLICATION_JSON))
.andExpect(status().isBadRequest());
}

@Test
public void should_not_create_namespace_when_user_is_not_member_of_group() throws Exception {
Region region = new Region();
Region.Services servicesConfiguration = new Region.Services();
servicesConfiguration.setSingleNamespace(false);
servicesConfiguration.setAllowNamespaceCreation(true);
region.setServices(servicesConfiguration);

when(regionsConfiguration.getDefaultRegion()).thenReturn(region);
when(userProvider.getUser(any())).thenReturn(User.newInstance().setIdep("default").build());

var onboardingRequest = new OnboardingController.OnboardingRequest();
onboardingRequest.setGroup("some-group");
mockMvc.perform(
post("/onboarding")
.content(mapper.writeValueAsString(onboardingRequest))
.contentType(APPLICATION_JSON))
.andExpect(status().isForbidden());
}

@Test
public void should_not_create_namespace_when_already_exist() throws Exception {
Region region = new Region();
Region.Services servicesConfiguration = new Region.Services();
servicesConfiguration.setSingleNamespace(false);
servicesConfiguration.setAllowNamespaceCreation(true);
region.setServices(servicesConfiguration);
when(regionsConfiguration.getDefaultRegion()).thenReturn(region);
when(userProvider.getUser(any())).thenReturn(User.newInstance().setIdep("default").build());
when(kubernetesService.createDefaultNamespace(any(), any()))
.thenThrow(new NamespaceAlreadyExistException());

mockMvc.perform(post("/onboarding").content("{}").contentType(APPLICATION_JSON))
.andExpect(status().isConflict());
}

@Test
public void should_create_namespace() throws Exception {
Region region = new Region();
Region.Services servicesConfiguration = new Region.Services();
servicesConfiguration.setSingleNamespace(false);
servicesConfiguration.setAllowNamespaceCreation(true);
region.setServices(servicesConfiguration);
when(regionsConfiguration.getDefaultRegion()).thenReturn(region);
when(userProvider.getUser(any())).thenReturn(User.newInstance().setIdep("default").build());
mockMvc.perform(post("/onboarding").content("{}").contentType(APPLICATION_JSON))
.andExpect(status().isOk());
}
}

0 comments on commit 777a0af

Please sign in to comment.