Skip to content

Commit

Permalink
✨ : add backend implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
juwit committed Aug 12, 2022
1 parent 4f9462e commit b6513f3
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.gaia_app.modules.repository.TerraformModuleRepository;
import io.gaia_app.registries.service.RegistryService;
import io.gaia_app.organizations.User;
import io.gaia_app.stacks.repository.StackRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
Expand Down Expand Up @@ -34,12 +35,15 @@ public class ModuleRestController {

private ModuleService moduleService;

private StackRepository stackRepository;

@Autowired
public ModuleRestController(TerraformModuleRepository moduleRepository, TerraformModuleGitRepository moduleGitRepository, RegistryService registryService, ModuleService moduleService) {
public ModuleRestController(TerraformModuleRepository moduleRepository, TerraformModuleGitRepository moduleGitRepository, RegistryService registryService, ModuleService moduleService, StackRepository stackRepository) {
this.moduleRepository = moduleRepository;
this.moduleGitRepository = moduleGitRepository;
this.registryService = registryService;
this.moduleService = moduleService;
this.stackRepository = stackRepository;
}

@GetMapping
Expand Down Expand Up @@ -86,6 +90,22 @@ public TerraformModule saveModule(@PathVariable String id, @RequestBody @Valid T
return moduleRepository.save(module);
}

@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteModule(@PathVariable String id, User user) {
var existingModule = moduleRepository.findById(id).orElseThrow(ModuleNotFoundException::new);
if (!existingModule.isAuthorizedFor(user)) {
throw new ModuleForbiddenException();
}

// find if module is still used by stacks
if( this.stackRepository.countStacksByModule(existingModule) > 0 ){
throw new CannotDeleteModuleException();
}

moduleRepository.delete(existingModule);
}

@GetMapping(value = "/{id}/readme", produces = MediaType.TEXT_PLAIN_VALUE)
public String readme(@PathVariable String id) {
var module = moduleRepository.findById(id).orElseThrow();
Expand Down Expand Up @@ -129,3 +149,11 @@ class ModuleNotFoundException extends RuntimeException {
class ModuleForbiddenException extends RuntimeException {
}

@ResponseStatus(HttpStatus.BAD_REQUEST)
class CannotDeleteModuleException extends RuntimeException {

public CannotDeleteModuleException() {
super("Module cannot be deleted as some stacks still use it.");
}
}

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.gaia_app.stacks.repository

import io.gaia_app.modules.bo.TerraformModule
import io.gaia_app.stacks.bo.Stack
import io.gaia_app.stacks.bo.StackState
import io.gaia_app.organizations.Organization
Expand All @@ -16,6 +17,7 @@ interface StackRepository : MongoRepository<Stack, String> {
fun countStacksByStateAndOwnerOrganization(state: StackState, organization: Organization): Long
fun countStacksByStateAndCreatedBy(state: StackState, user: User): Long
fun countStacksByState(state: StackState): Long
fun countStacksByModule(module: TerraformModule): Long
fun findByCreatedBy(userWithNoOrganization: User): List<Stack>
fun findByOwnerOrganization(organization: Organization): List<Stack>
fun findByIdAndOwnerOrganization(id: String, organization: Organization): Optional<Stack>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.gaia_app.test.SharedMongoContainerTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
Expand Down Expand Up @@ -34,6 +35,7 @@ void setup() {
mongo.runScript("00_organization.js");
mongo.runScript("10_user.js");
mongo.runScript("20_module.js");
mongo.runScript("30_stack.js");
}

@Test
Expand Down Expand Up @@ -167,4 +169,33 @@ void createModule_shouldSaveAModule() throws Exception {
.andExpect(jsonPath("$.name", is("new-module")));
}

@Nested
class DeleteModule{

@Test
@WithMockUser("Mary J")
void deleteModule_shouldNotBeAuthorized_forWrongUser() throws Exception {
mockMvc.perform(delete("/api/modules/e01f9925-a559-45a2-8a55-f93dc434c676")
.with(csrf()))
.andExpect(status().isForbidden());
}

@Test
void deleteModule_shouldNotBeAuthorized_withExistingStacks() throws Exception {
mockMvc.perform(delete("/api/modules/e01f9925-a559-45a2-8a55-f93dc434c676")
.with(csrf()))
.andExpect(status().isBadRequest());
}

@Test
void deleteModule_shouldWork_forModuleWithoutStacks() throws Exception {
mockMvc.perform(delete("/api/modules/b39ccd07-80f5-455f-a6b3-b94f915738c4")
.with(csrf()))
.andExpect(status().isNoContent());
}


}

}

Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
import io.gaia_app.organizations.Organization;
import io.gaia_app.organizations.User;
import io.gaia_app.modules.bo.TerraformModule;
import io.gaia_app.stacks.repository.StackRepository;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
Expand Down Expand Up @@ -44,6 +46,9 @@ class ModuleRestControllerTest {
@Mock
private ModuleService moduleService;

@Mock
private StackRepository stackRepository;

private User admin;

private User bob;
Expand Down Expand Up @@ -274,4 +279,56 @@ void refreshModule_shouldRefreshModuleVariablesAndOutputs(){
assertThat(module.getModuleMetadata().getUpdatedBy()).isEqualTo(bob);
}

@Nested
class DeleteModules {
@Test
void deleteModule_shouldDeleteUnusedModule(){
// given
var module = new TerraformModule();
module.getModuleMetadata().setCreatedBy(bob);
when(moduleRepository.findById("12")).thenReturn(Optional.of(module));

when(stackRepository.countStacksByModule(module)).thenReturn(0L);

// when
moduleRestController.deleteModule("12", bob);

// then
verify(moduleRepository).findById("12");
verify(moduleRepository).delete(module);
}

@Test
void deleteModule_shouldThrowAnException_ifModuleIsInUse(){
// given
var module = new TerraformModule();
module.getModuleMetadata().setCreatedBy(bob);
when(moduleRepository.findById("12")).thenReturn(Optional.of(module));

when(stackRepository.countStacksByModule(module)).thenReturn(1L);

// when
assertThrows(CannotDeleteModuleException.class, () -> moduleRestController.deleteModule("12", bob));

// then
verify(moduleRepository).findById("12");
verifyNoMoreInteractions(moduleRepository);
}

@Test
void deleteModule_shouldThrowAnException_ifModuleIsUnauthorizedForUser(){
// given
var module = new TerraformModule();
module.getModuleMetadata().setCreatedBy(john);
when(moduleRepository.findById("12")).thenReturn(Optional.of(module));

// when
assertThrows(ModuleForbiddenException.class, () -> moduleRestController.deleteModule("12", bob));

// then
verify(moduleRepository).findById("12");
verifyNoMoreInteractions(moduleRepository);
}
}

}

0 comments on commit b6513f3

Please sign in to comment.