diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a65ff76acacf6388c7b6d5f71304977b3fa81a94..f59a90d239a8c030b2eec0561c5a26b719cf4e20 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,6 +12,18 @@ test: - chmod +x ./gradlew - ./gradlew -Dorg.gradle.daemon=false test +itest: + stage: test + image: openjdk:11-jdk-slim + tags: + - docker + only: + - develop + - /^release/ + script: + - chmod +x ./gradlew + - ./gradlew integrationTest jacocoTestCoverageVerification + sonar: stage: sonar image: openjdk:17-jdk-slim diff --git a/src/integrationTest/java/net/geant/nmaas/portal/api/auth/SSOAuthControllerIntTest.java b/src/integrationTest/java/net/geant/nmaas/portal/api/auth/SSOAuthControllerIntTest.java index 46ff082c69def2a9049a06cde922e83a562b46bb..16867a493aa6aba9e7530a98c65ebb98737f6de4 100644 --- a/src/integrationTest/java/net/geant/nmaas/portal/api/auth/SSOAuthControllerIntTest.java +++ b/src/integrationTest/java/net/geant/nmaas/portal/api/auth/SSOAuthControllerIntTest.java @@ -149,7 +149,7 @@ public class SSOAuthControllerIntTest extends BaseControllerTestSetup { private void addLanguage(){ if(!intService.getEnabledLanguages().contains("en")) { - intService.addNewLanguage(new InternationalizationView("en", true, "{\"content\":\"content\"}")); + intService.addNewLanguage(new InternationalizationView("en", true, "{\"content\":\"content\"}"), false); } } diff --git a/src/integrationTest/java/net/geant/nmaas/portal/api/configuration/TestCacheConfig.java b/src/integrationTest/java/net/geant/nmaas/portal/api/configuration/TestCacheConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..fd403805673a5576f1b2b83d4585dab6a8feb50c --- /dev/null +++ b/src/integrationTest/java/net/geant/nmaas/portal/api/configuration/TestCacheConfig.java @@ -0,0 +1,15 @@ +package net.geant.nmaas.portal.api.configuration; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.cache.CacheManager; +import org.springframework.cache.support.NoOpCacheManager; +import org.springframework.context.annotation.Bean; + +@TestConfiguration +public class TestCacheConfig { + + @Bean + public CacheManager cacheManager() { + return new NoOpCacheManager(); + } +} diff --git a/src/integrationTest/java/net/geant/nmaas/portal/api/market/ApplicationControllerIntTest.java b/src/integrationTest/java/net/geant/nmaas/portal/api/market/ApplicationControllerIntTest.java index f2f9b6b7ffaa5b3e0f43fbd100b2a2cc08fe3bd6..2610b3835da4de89dfd98af32cea7d318f198547 100644 --- a/src/integrationTest/java/net/geant/nmaas/portal/api/market/ApplicationControllerIntTest.java +++ b/src/integrationTest/java/net/geant/nmaas/portal/api/market/ApplicationControllerIntTest.java @@ -15,6 +15,7 @@ import net.geant.nmaas.orchestration.entities.AppAccessMethod; import net.geant.nmaas.orchestration.entities.AppDeploymentSpec; import net.geant.nmaas.orchestration.entities.AppStorageVolume; import net.geant.nmaas.portal.api.BaseControllerTestSetup; +import net.geant.nmaas.portal.api.configuration.TestCacheConfig; import net.geant.nmaas.portal.api.domain.AppAccessMethodView; import net.geant.nmaas.portal.api.domain.AppConfigurationSpecView; import net.geant.nmaas.portal.api.domain.AppDeploymentSpecView; @@ -44,6 +45,8 @@ import org.junit.jupiter.api.Test; import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MvcResult; @@ -65,8 +68,9 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@SpringBootTest +@SpringBootTest(properties = "spring.cache.type=none") @Log4j2 +@Import(TestCacheConfig.class) class ApplicationControllerIntTest extends BaseControllerTestSetup { @Autowired @@ -104,13 +108,13 @@ class ApplicationControllerIntTest extends BaseControllerTestSetup { this.testApp1 = this.applicationService.create(getDefaultApplication(APP_1_NAME, "1.1.0", ApplicationState.ACTIVE)); this.testApp1Base.getVersions().addAll( List.of( - new ApplicationVersion(this.testApp1.getVersion(), this.testApp1.getState(), this.testApp1.getId()), - new ApplicationVersion("1.1.1", - ApplicationState.ACTIVE, - this.applicationService.create(getDefaultApplication(APP_1_NAME, "1.1.1", ApplicationState.ACTIVE)).getId()), - new ApplicationVersion("1.1.2", - ApplicationState.DISABLED, - this.applicationService.create(getDefaultApplication(APP_1_NAME, "1.1.2", ApplicationState.DISABLED)).getId()) + new ApplicationVersion(this.testApp1.getVersion(), this.testApp1.getState(), this.testApp1.getId()), + new ApplicationVersion("1.1.1", + ApplicationState.ACTIVE, + this.applicationService.create(getDefaultApplication(APP_1_NAME, "1.1.1", ApplicationState.ACTIVE)).getId()), + new ApplicationVersion("1.1.2", + ApplicationState.DISABLED, + this.applicationService.create(getDefaultApplication(APP_1_NAME, "1.1.2", ApplicationState.DISABLED)).getId()) ) ); this.testApp1Base = this.applicationBaseService.update(this.testApp1Base); @@ -130,8 +134,8 @@ class ApplicationControllerIntTest extends BaseControllerTestSetup { } @Test + @CacheEvict(value = "applicationBaseS", allEntries = true) void shouldGetActiveApplications() throws Exception { - log.debug("Test = {} {}", this.applicationBaseRepository.findAll().size(), this.applicationBaseRepository.findAllSmall().size()); MvcResult result = mvc.perform(get("/api/apps/base") .header("Authorization", "Bearer " + getValidTokenForUser(UsersHelper.ADMIN)) .accept(MediaType.APPLICATION_JSON)) diff --git a/src/integrationTest/java/net/geant/nmaas/portal/service/impl/BulkDomainServiceIntTest.java b/src/integrationTest/java/net/geant/nmaas/portal/service/impl/BulkDomainServiceIntTest.java index 5448d3102f6dc6e34acbb891744c41bc5544e616..9f3472bb31d66fca6069683d696c8dbfc0d24262 100644 --- a/src/integrationTest/java/net/geant/nmaas/portal/service/impl/BulkDomainServiceIntTest.java +++ b/src/integrationTest/java/net/geant/nmaas/portal/service/impl/BulkDomainServiceIntTest.java @@ -80,7 +80,7 @@ public class BulkDomainServiceIntTest { List<BulkDeployment> bulkDeployments = bulkDeploymentRepository.findAll(); assertEquals(1, bulkDeployments.size()); BulkDeployment bulkDeployment = bulkDeployments.get(0); - assertEquals(1, bulkDeployment.getCreatorId()); + assertEquals(1, bulkDeployment.getCreator().getId()); assertEquals(BulkType.DOMAIN, bulkDeployment.getType()); assertEquals(6, bulkDeployment.getEntries().size()); assertThat(userRepository.findByEmail("user1@test.com").orElseThrow().getSamlToken()).isEqualTo("user1@test.com"); @@ -105,7 +105,7 @@ public class BulkDomainServiceIntTest { List<BulkDeployment> bulkDeployments = bulkDeploymentRepository.findAll(); assertEquals(1, bulkDeployments.size()); BulkDeployment bulkDeployment = bulkDeployments.get(0); - assertEquals(1, bulkDeployment.getCreatorId()); + assertEquals(1, bulkDeployment.getCreator().getId()); assertEquals(BulkType.DOMAIN, bulkDeployment.getType()); assertEquals(4, bulkDeployment.getEntries().size()); assertThat(userRepository.findByEmail("user1@test.com").orElseThrow().getSamlToken()).isNull(); @@ -128,7 +128,7 @@ public class BulkDomainServiceIntTest { List<BulkDeployment> bulkDeployments = bulkDeploymentRepository.findAll(); assertEquals(1, bulkDeployments.size()); BulkDeployment bulkDeployment = bulkDeployments.get(0); - assertEquals(1, bulkDeployment.getCreatorId()); + assertEquals(1, bulkDeployment.getCreator().getId()); assertEquals(BulkType.DOMAIN, bulkDeployment.getType()); assertEquals(6, bulkDeployment.getEntries().size()); assertEquals("testdomain10", bulkDeployment.getEntries().get(0).getDetails().get("domainCodename")); diff --git a/src/integrationTest/resources/application.properties b/src/integrationTest/resources/application.properties index c11717acbcc34cda752d6e0fe39cf003c3ad5e0a..3c84a841647ce27a53b71534a60d0499f11ca22c 100644 --- a/src/integrationTest/resources/application.properties +++ b/src/integrationTest/resources/application.properties @@ -161,3 +161,5 @@ portal.config.sendAppInstanceFailureEmails=false portal.config.showDomainRegistrationSelector=true # string - list of emails with ':' as a separator, e.g., admin1@nmaas.eu;admin2@nmaas.eu portal.config.appInstanceFailureEmailList=admin@nmaas.eu + +spring.cache.type=none diff --git a/src/main/java/net/geant/nmaas/MainConfig.java b/src/main/java/net/geant/nmaas/MainConfig.java index 925bf1973c9d12fb69ad6b43cf55e652ca25c9bd..dfdb09578723b604d901a258d7c8fe45d4748659 100644 --- a/src/main/java/net/geant/nmaas/MainConfig.java +++ b/src/main/java/net/geant/nmaas/MainConfig.java @@ -2,6 +2,7 @@ package net.geant.nmaas; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.event.ApplicationEventMulticaster; @@ -14,6 +15,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @SpringBootApplication @EnableScheduling @EnableAspectJAutoProxy +@EnableCaching public class MainConfig { public static void main(String[] args) { diff --git a/src/main/java/net/geant/nmaas/notifications/templates/TemplateController.java b/src/main/java/net/geant/nmaas/notifications/templates/TemplateController.java index eb7360265f043c4d7183f1fb819d1bf118241c3e..9483df6b814e2cf99cf4c76e7ebdc0bb7e2a0183 100644 --- a/src/main/java/net/geant/nmaas/notifications/templates/TemplateController.java +++ b/src/main/java/net/geant/nmaas/notifications/templates/TemplateController.java @@ -2,9 +2,12 @@ package net.geant.nmaas.notifications.templates; import lombok.RequiredArgsConstructor; import net.geant.nmaas.notifications.templates.api.MailTemplateView; +import net.geant.nmaas.portal.exceptions.ConfigurationNotFoundException; +import net.geant.nmaas.portal.exceptions.DataConflictException; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -69,4 +72,10 @@ public class TemplateController { public void updateHtmlTemplate(@RequestBody MultipartFile file){ this.templateService.updateHTMLTemplate(file); } + + @ExceptionHandler(DataConflictException.class) + @ResponseStatus(code = HttpStatus.CONFLICT) + public String handleDataConfigException(DataConflictException e){ + return e.getMessage(); + } } diff --git a/src/main/java/net/geant/nmaas/notifications/templates/TemplateService.java b/src/main/java/net/geant/nmaas/notifications/templates/TemplateService.java index bd5e379074d368442afbaee550026533fdb6ba15..8f8cb8d92efd736aeeb4a8b7a837d172780e1d0e 100644 --- a/src/main/java/net/geant/nmaas/notifications/templates/TemplateService.java +++ b/src/main/java/net/geant/nmaas/notifications/templates/TemplateService.java @@ -7,6 +7,7 @@ import net.geant.nmaas.notifications.templates.api.MailTemplateView; import net.geant.nmaas.notifications.templates.entities.LanguageMailContent; import net.geant.nmaas.notifications.templates.entities.MailTemplate; import net.geant.nmaas.notifications.templates.repository.MailTemplateRepository; +import net.geant.nmaas.portal.exceptions.DataConflictException; import net.geant.nmaas.portal.persistent.entity.FileInfo; import net.geant.nmaas.portal.service.impl.LocalFileStorageService; import org.modelmapper.ModelMapper; @@ -24,6 +25,7 @@ import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkArgument; + @Service public class TemplateService { @@ -34,26 +36,26 @@ public class TemplateService { private LocalFileStorageService fileStorageService; @Autowired - public TemplateService(MailTemplateRepository repository, LocalFileStorageService fileStorageService, ModelMapper modelMapper){ + public TemplateService(MailTemplateRepository repository, LocalFileStorageService fileStorageService, ModelMapper modelMapper) { this.modelMapper = modelMapper; this.repository = repository; this.fileStorageService = fileStorageService; } @Transactional - public MailTemplateView getMailTemplate(MailType mailType){ + public MailTemplateView getMailTemplate(MailType mailType) { MailTemplate mailTemplate = repository.findByMailType(mailType).orElseThrow(() -> new IllegalArgumentException("Mail template not found")); return modelMapper.map(mailTemplate, MailTemplateView.class); } - List<MailTemplateView> getMailTemplates(){ + List<MailTemplateView> getMailTemplates() { return this.repository.findAll().stream() .map(mailTemplate -> modelMapper.map(mailTemplate, MailTemplateView.class)) .collect(Collectors.toList()); } void saveMailTemplate(MailTemplateView mailTemplate) { - checkArgument(!repository.existsByMailType(mailTemplate.getMailType()),"Mail template already exists"); + checkArgumentConflict(!repository.existsByMailType(mailTemplate.getMailType()), String.format("Mail template %s already exists", mailTemplate.getMailType().name())); checkArgument(mailTemplate.getTemplates() != null && !mailTemplate.getTemplates().isEmpty(), "Mail template cannot be null or empty"); repository.save(modelMapper.map(mailTemplate, MailTemplate.class)); } @@ -69,11 +71,11 @@ public class TemplateService { void storeHTMLTemplate(MultipartFile file) { checkArgument(file != null && !file.isEmpty(), "HTML template cannot be null or empty"); checkArgument(Objects.equals(file.getContentType(), MailTemplateElements.HTML_TYPE), "HTML template must be in html format"); - checkArgument(fileStorageService.getFileInfoByContentType(MailTemplateElements.HTML_TYPE).isEmpty(), "Only one HTML template is supported."); + checkArgumentConflict(fileStorageService.getFileInfoByContentType(MailTemplateElements.HTML_TYPE).isEmpty(), "Only one HTML template is supported."); fileStorageService.store(file); } - void updateHTMLTemplate(MultipartFile file){ + void updateHTMLTemplate(MultipartFile file) { FileInfo fileInfo = getHTMLTemplateFileInfo(); if (fileStorageService.remove(fileInfo)) { storeHTMLTemplate(file); @@ -93,4 +95,10 @@ public class TemplateService { throw new IllegalArgumentException(String.format("Exactly one html template supported (actually got %d)", template.size())); } + private static void checkArgumentConflict(boolean expression, String errorMessage) { + if (!expression) { + throw new DataConflictException(String.valueOf(errorMessage)); + } + } + } diff --git a/src/main/java/net/geant/nmaas/notifications/types/FormTypeController.java b/src/main/java/net/geant/nmaas/notifications/types/FormTypeController.java index 196e841f29e8657362b527dc2a172d3b7faaae50..55172bac6d5d87469745f92f3d22f29e69732c33 100644 --- a/src/main/java/net/geant/nmaas/notifications/types/FormTypeController.java +++ b/src/main/java/net/geant/nmaas/notifications/types/FormTypeController.java @@ -4,8 +4,10 @@ import lombok.AllArgsConstructor; import net.geant.nmaas.notifications.types.model.FormTypeRequest; import net.geant.nmaas.notifications.types.model.FormTypeView; import net.geant.nmaas.notifications.types.service.FormTypeService; +import net.geant.nmaas.portal.exceptions.DataConflictException; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -35,4 +37,9 @@ public class FormTypeController { this.service.create(request); } + @ExceptionHandler(DataConflictException.class) + @ResponseStatus(code = HttpStatus.CONFLICT) + public String handleDataConfigException(DataConflictException e){ + return e.getMessage(); + } } diff --git a/src/main/java/net/geant/nmaas/notifications/types/service/FormTypeService.java b/src/main/java/net/geant/nmaas/notifications/types/service/FormTypeService.java index 06e47911bcee234f21b41bf257f6e3a4be06f91f..21426f5f5f09d240b3fe1b6ac0bc6d37589663fe 100644 --- a/src/main/java/net/geant/nmaas/notifications/types/service/FormTypeService.java +++ b/src/main/java/net/geant/nmaas/notifications/types/service/FormTypeService.java @@ -6,6 +6,7 @@ import net.geant.nmaas.notifications.types.model.FormTypeView; import net.geant.nmaas.notifications.types.persistence.entity.FormType; import net.geant.nmaas.notifications.types.persistence.repository.FormTypeRepository; import net.geant.nmaas.portal.api.exception.ProcessingException; +import net.geant.nmaas.portal.exceptions.DataConflictException; import org.springframework.stereotype.Service; import java.util.List; @@ -32,7 +33,7 @@ public class FormTypeService { if(!this.typeRepository.existsById(ent.getKeyValue())) { this.typeRepository.save(ent); } else { - throw new ProcessingException("Form type already exists"); + throw new DataConflictException(String.format("Form type %s already exists", ent.getTemplateName())); } } diff --git a/src/main/java/net/geant/nmaas/orchestration/entities/AppDeploymentState.java b/src/main/java/net/geant/nmaas/orchestration/entities/AppDeploymentState.java index c2e1582545c79b3cc0530b5741f841a806405754..b35e07d6321a576a04040fb6928e7bd8cd4c0c96 100644 --- a/src/main/java/net/geant/nmaas/orchestration/entities/AppDeploymentState.java +++ b/src/main/java/net/geant/nmaas/orchestration/entities/AppDeploymentState.java @@ -412,10 +412,15 @@ public enum AppDeploymentState { @Override public AppDeploymentState nextState(NmServiceDeploymentState state) { - if (NmServiceDeploymentState.CONFIGURATION_REMOVAL_INITIATED.equals(state)) { - return APPLICATION_CONFIGURATION_REMOVAL_IN_PROGRESS; + switch (state) { + case DEPLOYMENT_FAILED: + return APPLICATION_DEPLOYMENT_FAILED; + case CONFIGURATION_REMOVAL_INITIATED: + return APPLICATION_CONFIGURATION_REMOVAL_IN_PROGRESS; + default: + return nextStateForNotMatchingNmServiceDeploymentState(this, state); } - return nextStateForNotMatchingNmServiceDeploymentState(this, state); + } @Override diff --git a/src/main/java/net/geant/nmaas/portal/api/bulk/BulkController.java b/src/main/java/net/geant/nmaas/portal/api/bulk/BulkController.java index 6b8ba758c3a7825d5567610736b9729abcb7fce4..a709fbf62344c7da55cc57f74c52919778571c07 100644 --- a/src/main/java/net/geant/nmaas/portal/api/bulk/BulkController.java +++ b/src/main/java/net/geant/nmaas/portal/api/bulk/BulkController.java @@ -117,7 +117,7 @@ public class BulkController { log.info("Processing bulk application deployment details request"); BulkDeployment bulk = bulkDeploymentRepository.findById(id).orElseThrow(); BulkDeploymentView bulkView = modelMapper.map(bulk, BulkDeploymentView.class); - bulkView.setCreator(getUserView(bulk.getCreatorId())); + bulkView.setCreator(getUserView(bulk.getCreator().getId())); mapDetails(bulk, bulkView); List<BulkAppDetails> details = bulkApplicationService.getAppsBulkDetails(bulkView); InputStreamResource inputStreamResource = bulkApplicationService.getInputStreamAppBulkDetails(details); @@ -172,7 +172,7 @@ public class BulkController { return ResponseEntity.notFound().build(); } - if(bulk.get().getCreatorId().equals(user.getId()) ) { + if(bulk.get().getCreator().getId().equals(user.getId()) ) { throw new PermissionDeniedDataAccessException("User doesnt have access to this bulk deployment", new Throwable()); } if (removeApps) { @@ -203,9 +203,9 @@ public class BulkController { private <T extends BulkDeploymentViewS> T mapToView(BulkDeployment bulk, Class<T> viewType) { T bulkView = modelMapper.map(bulk, viewType); try { - bulkView.setCreator(getUserView(bulk.getCreatorId())); + bulkView.setCreator(getUserView(bulk.getCreator().getId())); } catch (Exception ex) { - log.error("Can not find creator for {} - creatorId: {}", bulk.getId(), bulk.getCreatorId()); + log.error("Can not find creator for {} - creatorId: {}", bulk.getId(), bulk.getCreator().getId()); return null; } mapDetails(bulk, bulkView); @@ -215,14 +215,13 @@ public class BulkController { private BulkDeploymentView mapToView(BulkDeployment deployment) { BulkDeploymentView bulkView = modelMapper.map(deployment, BulkDeploymentView.class); try { - bulkView.setCreator(getUserView(deployment.getCreatorId())); - } catch (Exception ex) { - log.error("Can not find creator for {} - creatorId: {}", deployment.getId(), deployment.getCreatorId()); + bulkView.setCreator(getUserView(deployment.getCreator().getId())); return null; + } catch (Exception ex) { + log.error("Can not find creator for {} - creatorId: {}", deployment.getId(), deployment.getCreator().getId()); } mapDetails(deployment, bulkView); return bulkView; - } private void mapDetails(BulkDeployment deployment, BulkDeploymentViewS view) { diff --git a/src/main/java/net/geant/nmaas/portal/api/i18n/InternationalizationController.java b/src/main/java/net/geant/nmaas/portal/api/i18n/InternationalizationController.java index b15cbed12ac66b8d91c60499213fb100cfe58f29..2fb0cca6e9508f36c42d2f27eca995f85188be97 100644 --- a/src/main/java/net/geant/nmaas/portal/api/i18n/InternationalizationController.java +++ b/src/main/java/net/geant/nmaas/portal/api/i18n/InternationalizationController.java @@ -1,13 +1,23 @@ package net.geant.nmaas.portal.api.i18n; -import java.util.List; import lombok.AllArgsConstructor; import net.geant.nmaas.portal.api.i18n.api.InternationalizationBriefView; import net.geant.nmaas.portal.api.i18n.api.InternationalizationView; import net.geant.nmaas.portal.service.InternationalizationService; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; @RestController @AllArgsConstructor @@ -19,35 +29,37 @@ public class InternationalizationController { @PostMapping("/{language}") @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN')") @ResponseStatus(HttpStatus.ACCEPTED) - public void saveLanguageContent(@PathVariable("language") String language, @RequestParam(value = "enabled") boolean enabled, @RequestBody String content) { - this.internationalizationService.addNewLanguage(new InternationalizationView(language, enabled, content)); + public void saveLanguageContent(@PathVariable("language") String language, @RequestParam(value = "enabled") boolean enabled, + @RequestParam(value = "force", required = false, defaultValue = "false") Boolean force, @RequestBody String content) { + boolean isForce = force != null && force; + this.internationalizationService.addNewLanguage(new InternationalizationView(language, enabled, content), isForce); } @PatchMapping("/{language}") @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN') || hasRole('ROLE_TOOL_MANAGER')") @ResponseStatus(HttpStatus.ACCEPTED) - public void updateLanguageContent(@PathVariable("language") String language, @RequestBody String content){ + public void updateLanguageContent(@PathVariable("language") String language, @RequestBody String content) { this.internationalizationService.updateLanguage(language, content); } @GetMapping("/all") @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN') || hasRole('ROLE_TOOL_MANAGER')") @ResponseStatus(HttpStatus.OK) - public List<InternationalizationBriefView> getAllSupportedLanguages(){ + public List<InternationalizationBriefView> getAllSupportedLanguages() { return this.internationalizationService.getAllSupportedLanguages(); } @GetMapping("/{language}") @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN')") @ResponseStatus(HttpStatus.OK) - public InternationalizationView getLanguage(@PathVariable String language){ + public InternationalizationView getLanguage(@PathVariable String language) { return this.internationalizationService.getLanguage(language); } @PutMapping("/state") @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN')") @ResponseStatus(HttpStatus.NO_CONTENT) - public void changeSupportedLanguageState(@RequestBody InternationalizationBriefView language){ + public void changeSupportedLanguageState(@RequestBody InternationalizationBriefView language) { this.internationalizationService.changeLanguageState(language); } @@ -59,7 +71,7 @@ public class InternationalizationController { @GetMapping("/all/enabled") @ResponseStatus(HttpStatus.OK) - public List<String> getEnabledLanguages(){ + public List<String> getEnabledLanguages() { return this.internationalizationService.getEnabledLanguages(); } } diff --git a/src/main/java/net/geant/nmaas/portal/api/market/DomainController.java b/src/main/java/net/geant/nmaas/portal/api/market/DomainController.java index 382d56837ed860706f18722698073f05f0d90018..36707803c8f01913792daaa58f1c4850e5756b80 100644 --- a/src/main/java/net/geant/nmaas/portal/api/market/DomainController.java +++ b/src/main/java/net/geant/nmaas/portal/api/market/DomainController.java @@ -16,6 +16,7 @@ import net.geant.nmaas.portal.api.domain.DomainRequest; import net.geant.nmaas.portal.api.domain.DomainView; import net.geant.nmaas.portal.api.domain.Id; import net.geant.nmaas.portal.api.domain.KeyValueView; +import net.geant.nmaas.portal.api.domain.UserViewMinimal; import net.geant.nmaas.portal.api.exception.MissingElementException; import net.geant.nmaas.portal.api.exception.ProcessingException; import net.geant.nmaas.portal.exceptions.ObjectNotFoundException; @@ -310,6 +311,19 @@ public class DomainController extends AppBaseController { } } + @PutMapping("/group/members/{domainGroupId}") + @Transactional + @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN') || hasRole('ROLE_VL_MANAGER')") + public DomainGroupView updateDomainGroupMembers(@PathVariable Long domainGroupId, @RequestBody List<UserViewMinimal> members, Principal principal) throws AccessDeniedException { + DomainGroupView domainGroup = domainGroupService.getDomainGroup(domainGroupId); + if (getUser(principal.getName()).getRoles().stream().anyMatch(userRole -> userRole.getRole().equals(Role.ROLE_SYSTEM_ADMIN)) || + domainGroup.getManagers().stream().anyMatch(user -> user.getUsername().equalsIgnoreCase(principal.getName()))) { + return domainService.updateMembers(members, domainGroup); + } else { + throw new AccessDeniedException("You have no access to this domain group"); + } + } + @GetMapping("/annotations") @Transactional @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN')") diff --git a/src/main/java/net/geant/nmaas/portal/api/security/CustomAccessTokenController.java b/src/main/java/net/geant/nmaas/portal/api/security/CustomAccessTokenController.java new file mode 100644 index 0000000000000000000000000000000000000000..66839fd385cb64d9b4750081062a1813a348a2de --- /dev/null +++ b/src/main/java/net/geant/nmaas/portal/api/security/CustomAccessTokenController.java @@ -0,0 +1,52 @@ +package net.geant.nmaas.portal.api.security; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import net.geant.nmaas.portal.exceptions.ObjectNotFoundException; +import net.geant.nmaas.portal.persistent.entity.AccessToken; +import net.geant.nmaas.portal.persistent.entity.User; +import net.geant.nmaas.portal.service.CustomAccessTokenService; +import net.geant.nmaas.portal.service.UserService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.security.Principal; +import java.util.List; + +@RestController +@RequestMapping("/api/tokens") +@RequiredArgsConstructor +@Log4j2 +public class CustomAccessTokenController { + + private final CustomAccessTokenService accessTokenService; + private final UserService userService; + + @GetMapping() + public List<AccessToken> getAll(Principal principal) { + User user = getUser(principal); + return accessTokenService.getAll(user.getId()); + } + + @PostMapping() + public AccessToken createNewToken(Principal principal, @RequestBody String name) { + User user = getUser(principal); + return accessTokenService.createToken(user.getId(), name); + } + + @PutMapping("/{id}") + public void invalidateToken(@PathVariable Long id) { + accessTokenService.invalidate(id); + } + + private User getUser(Principal principal) { + String principalName = principal.getName(); + return userService.findByUsername(principalName) + .orElseThrow(() -> new ObjectNotFoundException("User not found")); + } +} diff --git a/src/main/java/net/geant/nmaas/portal/exceptions/DataConflictException.java b/src/main/java/net/geant/nmaas/portal/exceptions/DataConflictException.java new file mode 100644 index 0000000000000000000000000000000000000000..aadb9107d38765b83ff31410ef3ce3a42f346aa8 --- /dev/null +++ b/src/main/java/net/geant/nmaas/portal/exceptions/DataConflictException.java @@ -0,0 +1,12 @@ +package net.geant.nmaas.portal.exceptions; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class DataConflictException extends RuntimeException { + + public DataConflictException(String message) { + super(message); + } + +} diff --git a/src/main/java/net/geant/nmaas/portal/persistent/entity/AccessToken.java b/src/main/java/net/geant/nmaas/portal/persistent/entity/AccessToken.java new file mode 100644 index 0000000000000000000000000000000000000000..80c117b2a178e8aee330990a737638c0fdc42960 --- /dev/null +++ b/src/main/java/net/geant/nmaas/portal/persistent/entity/AccessToken.java @@ -0,0 +1,33 @@ +package net.geant.nmaas.portal.persistent.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "access_tokens") +@NoArgsConstructor +@Getter +@Setter +@AllArgsConstructor +public class AccessToken { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + private Long userId; + + private String tokenValue; + + private boolean valid; +} diff --git a/src/main/java/net/geant/nmaas/portal/persistent/entity/BulkDeployment.java b/src/main/java/net/geant/nmaas/portal/persistent/entity/BulkDeployment.java index 9d3357fc97603d12cd1fda89f5b63e52c52d3e6c..06a9a0b9fb7e4a0b0410b2d97971f33d84fb96c3 100644 --- a/src/main/java/net/geant/nmaas/portal/persistent/entity/BulkDeployment.java +++ b/src/main/java/net/geant/nmaas/portal/persistent/entity/BulkDeployment.java @@ -15,6 +15,8 @@ import javax.persistence.Enumerated; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import java.time.OffsetDateTime; import java.util.ArrayList; @@ -32,7 +34,9 @@ public class BulkDeployment { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - private Long creatorId; + @ManyToOne + @JoinColumn(name = "creator_id") + private User creator; private OffsetDateTime creationDate; diff --git a/src/main/java/net/geant/nmaas/portal/persistent/repositories/AccessTokenRepository.java b/src/main/java/net/geant/nmaas/portal/persistent/repositories/AccessTokenRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..7655ad0afff9c210f50cbf7c843ce22cf59fa7eb --- /dev/null +++ b/src/main/java/net/geant/nmaas/portal/persistent/repositories/AccessTokenRepository.java @@ -0,0 +1,12 @@ +package net.geant.nmaas.portal.persistent.repositories; + +import net.geant.nmaas.portal.persistent.entity.AccessToken; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface AccessTokenRepository extends JpaRepository<AccessToken, Long> { + List<AccessToken> findAllByUserId(Long userId); +} diff --git a/src/main/java/net/geant/nmaas/portal/persistent/repositories/ApplicationBaseRepository.java b/src/main/java/net/geant/nmaas/portal/persistent/repositories/ApplicationBaseRepository.java index f5398bb34523a769b2d28c4ea32363d345fda0e8..b4b89368be342af33ea85fe59099361792a5e927 100644 --- a/src/main/java/net/geant/nmaas/portal/persistent/repositories/ApplicationBaseRepository.java +++ b/src/main/java/net/geant/nmaas/portal/persistent/repositories/ApplicationBaseRepository.java @@ -4,6 +4,7 @@ import net.geant.nmaas.portal.api.domain.ApplicationBaseS; import net.geant.nmaas.portal.persistent.entity.AppDescription; import net.geant.nmaas.portal.persistent.entity.ApplicationBase; import net.geant.nmaas.portal.persistent.entity.Tag; +import org.springframework.cache.annotation.Cacheable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @@ -24,7 +25,8 @@ public interface ApplicationBaseRepository extends JpaRepository<ApplicationBase @Query("SELECT COUNT(DISTINCT ab.name) FROM ApplicationBase ab JOIN Application a on a.name = ab.name WHERE a.state = 'ACTIVE'") long countAllActive(); - @Query(value = "SELECT DISTINCT(ab.*) FROM application_base ab JOIN application_base_versions abv on abv.application_base_id = ab.id JOIN application_version av ON av.id = abv.versions_id WHERE av.state = 'ACTIVE'", nativeQuery = true) + @Cacheable("applicationBaseS") + @Query("SELECT DISTINCT ab FROM ApplicationBase ab JOIN Application a on a.name = ab.name WHERE a.state = 'ACTIVE'") List<ApplicationBaseS> findAllSmall(); @Query("SELECT ab.tags FROM ApplicationBase ab WHERE ab.id =?1") diff --git a/src/main/java/net/geant/nmaas/portal/service/BulkApplicationService.java b/src/main/java/net/geant/nmaas/portal/service/BulkApplicationService.java index 3d3a3d7c472afe3a743cda549713c5fa235439e7..1edd067a0359bdb06ee1d218c52cd3355d683ebd 100644 --- a/src/main/java/net/geant/nmaas/portal/service/BulkApplicationService.java +++ b/src/main/java/net/geant/nmaas/portal/service/BulkApplicationService.java @@ -25,7 +25,7 @@ public interface BulkApplicationService { List<BulkAppDetails> getAppsBulkDetails(BulkDeploymentView view); - InputStreamResource getInputStreamAppBulkDetails(List<BulkAppDetails> list ); + InputStreamResource getInputStreamAppBulkDetails(List<BulkAppDetails> list); void deleteAppInstancesFromBulk(BulkDeploymentView bulk); diff --git a/src/main/java/net/geant/nmaas/portal/service/CustomAccessTokenService.java b/src/main/java/net/geant/nmaas/portal/service/CustomAccessTokenService.java new file mode 100644 index 0000000000000000000000000000000000000000..96e59e1eb7a6960580be1e8a2d86095363fa7cf2 --- /dev/null +++ b/src/main/java/net/geant/nmaas/portal/service/CustomAccessTokenService.java @@ -0,0 +1,13 @@ +package net.geant.nmaas.portal.service; + +import net.geant.nmaas.portal.persistent.entity.AccessToken; + +import java.util.List; + +public interface CustomAccessTokenService { + + void invalidate(Long id); + AccessToken createToken(Long userId, String name); + List<AccessToken> getAll(Long userId); + +} diff --git a/src/main/java/net/geant/nmaas/portal/service/DomainService.java b/src/main/java/net/geant/nmaas/portal/service/DomainService.java index 70ff8d5da09e214176c0adb66cf87f280f79731b..a26f3b60c534c62f8ba3314438c281bcf5a1fc60 100644 --- a/src/main/java/net/geant/nmaas/portal/service/DomainService.java +++ b/src/main/java/net/geant/nmaas/portal/service/DomainService.java @@ -7,6 +7,7 @@ import net.geant.nmaas.portal.api.domain.DomainGroupView; import net.geant.nmaas.portal.api.domain.DomainRequest; import net.geant.nmaas.portal.api.domain.KeyValueView; import net.geant.nmaas.portal.api.domain.UserView; +import net.geant.nmaas.portal.api.domain.UserViewMinimal; import net.geant.nmaas.portal.persistent.entity.ApplicationBase; import net.geant.nmaas.portal.persistent.entity.Domain; import net.geant.nmaas.portal.persistent.entity.DomainAnnotation; @@ -70,6 +71,8 @@ public interface DomainService { void updateRolesInDomainGroupByUsers(DomainGroupView view); + DomainGroupView updateMembers(List<UserViewMinimal> newMembers, DomainGroupView view); + void addAnnotation(KeyValueView annotation); boolean checkIfAnnotationExist(String key); void deleteAnnotation(Long id); diff --git a/src/main/java/net/geant/nmaas/portal/service/InternationalizationService.java b/src/main/java/net/geant/nmaas/portal/service/InternationalizationService.java index 66a3e9a37021f8464d4eb8a6f776efab8dbcaf37..7806750f2a26ee791e1d5a6d2812018652850608 100644 --- a/src/main/java/net/geant/nmaas/portal/service/InternationalizationService.java +++ b/src/main/java/net/geant/nmaas/portal/service/InternationalizationService.java @@ -5,7 +5,7 @@ import net.geant.nmaas.portal.api.i18n.api.InternationalizationBriefView; import net.geant.nmaas.portal.api.i18n.api.InternationalizationView; public interface InternationalizationService { - void addNewLanguage(InternationalizationView newLanguage); + void addNewLanguage(InternationalizationView newLanguage, Boolean force); void updateLanguage(String language, String content); List<InternationalizationBriefView> getAllSupportedLanguages(); InternationalizationView getLanguage(String language); diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationBaseServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationBaseServiceImpl.java index d752b89635bc0e9cd666c077853de652fd1f0632..c0b95f5da87185627dd04fd29b20163599cc5117 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationBaseServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationBaseServiceImpl.java @@ -21,6 +21,8 @@ import net.geant.nmaas.portal.service.DomainService; import org.apache.commons.lang3.StringUtils; import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.CachePut; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; @@ -52,6 +54,7 @@ public class ApplicationBaseServiceImpl implements ApplicationBaseService { @Override @Transactional + @CachePut("applicationBaseS") public ApplicationBase create(ApplicationBase applicationBase) { if (applicationBase.getId() != null) { log.error("Cannot add ApplicationBase - id not null"); @@ -78,6 +81,7 @@ public class ApplicationBaseServiceImpl implements ApplicationBaseService { @Override @Transactional + @CachePut("applicationBaseS") public ApplicationBase update(ApplicationBase applicationBase) { if (applicationBase.getId() == null) { throw new ProcessingException("Updated entity id must not be null"); @@ -88,6 +92,7 @@ public class ApplicationBaseServiceImpl implements ApplicationBaseService { @Override @Transactional + @CachePut("applicationBaseS") public ApplicationBase updateOwner(Long id, String owner) { if (id == null) { throw new ProcessingException("Updated entity id must not be null"); @@ -104,6 +109,7 @@ public class ApplicationBaseServiceImpl implements ApplicationBaseService { } @Override + @CacheEvict(value = "applicationBaseS", allEntries = true) public void updateApplicationVersionState(String name, String version, ApplicationState state) { ApplicationBase appBase = findByName(name.contains(DELETED_MARKER) ? name.substring(0, name.indexOf(DELETED_MARKER)) : name); appBase.getVersions().stream() @@ -141,8 +147,6 @@ public class ApplicationBaseServiceImpl implements ApplicationBaseService { log.debug("Loaded base data from db in {}ms", end.toInstant(ZoneOffset.UTC).toEpochMilli() - beginning.toInstant(ZoneOffset.UTC).toEpochMilli()); List<ApplicationBaseViewS> result = allSmall.stream() .map(app -> modelMapper.map(app, ApplicationBaseViewS.class)) - .peek(app -> app.setDescriptions(List.of(modelMapper.map(appBaseRepository.findAllBaseDescription(app.getId()), AppDescriptionView[].class)))) - .peek(app -> app.setTags(Set.of(modelMapper.map(appBaseRepository.findAllBaseTag(app.getId()), TagView[].class)))) .collect(Collectors.toList()); LocalDateTime finish = LocalDateTime.now(); log.debug("Complete data is ready after next {}ms", finish.toInstant(ZoneOffset.UTC).toEpochMilli() - end.toInstant(ZoneOffset.UTC).toEpochMilli()); @@ -172,6 +176,7 @@ public class ApplicationBaseServiceImpl implements ApplicationBaseService { } @Override + @CacheEvict(value = "applicationBaseS", allEntries = true) public void deleteAppBase(ApplicationBase base) { base.setName(base.getName() + DELETED_MARKER + OffsetDateTime.now()); appBaseRepository.save(base); diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationServiceImpl.java index 47603ff775d7ca1f491fd82d279e6febf592d496..737e059dcf33b1fc2cb176b8f00bb6497dea64bb 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationServiceImpl.java @@ -13,6 +13,8 @@ import net.geant.nmaas.portal.persistent.entity.Application; import net.geant.nmaas.portal.persistent.entity.ApplicationState; import net.geant.nmaas.portal.persistent.repositories.ApplicationRepository; import net.geant.nmaas.portal.service.ApplicationService; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.CachePut; import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -42,6 +44,7 @@ public class ApplicationServiceImpl implements ApplicationService { @Override @Transactional + @CachePut("applicationBaseS") public Application update(Application application) { checkApp(application); Application saved = applicationRepository.save(application); @@ -66,6 +69,7 @@ public class ApplicationServiceImpl implements ApplicationService { } @Override + @CachePut("applicationBaseS") public Application create(Application application) { if (application.getId() != null) { throw new ProcessingException("While creating id must be null"); @@ -77,6 +81,7 @@ public class ApplicationServiceImpl implements ApplicationService { } @Override + @CacheEvict(value = "applicationBaseS") public void delete(Long id) { checkParam(id); applicationRepository.findById(id).ifPresent(app -> { @@ -123,6 +128,7 @@ public class ApplicationServiceImpl implements ApplicationService { } @Override + @CacheEvict(value = "applicationBaseS", allEntries = true) public void changeApplicationState(Application app, ApplicationState state) { if (!app.getState().isChangeAllowed(state)) { throw new IllegalStateException("Application state transition from " + app.getState() + " to " + state + " is not allowed."); diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/BulkApplicationServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/BulkApplicationServiceImpl.java index d2b6a4111f0009d004dd26d7b0eb1f1bdb49d5a5..87cae098abd5a6e1d6ba6994883b7d3b31ae6516 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/BulkApplicationServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/BulkApplicationServiceImpl.java @@ -37,6 +37,7 @@ import net.geant.nmaas.portal.service.ApplicationService; import net.geant.nmaas.portal.service.ApplicationSubscriptionService; import net.geant.nmaas.portal.service.BulkApplicationService; import net.geant.nmaas.portal.service.DomainService; +import net.geant.nmaas.portal.service.UserService; import org.apache.commons.collections4.MultiValuedMap; import org.jetbrains.annotations.NotNull; import org.modelmapper.ModelMapper; @@ -84,6 +85,7 @@ public class BulkApplicationServiceImpl implements BulkApplicationService { private final ApplicationService applicationService; private final DomainService domainService; private final ApplicationSubscriptionService applicationSubscriptionService; + private final UserService userService; private final ApplicationInstanceService instanceService; private final AppDeploymentMonitor appDeploymentMonitor; @@ -342,9 +344,12 @@ public class BulkApplicationServiceImpl implements BulkApplicationService { @Override public void setBulkEntryToProcessing(Long bulkEntryId) { - BulkDeploymentEntry entry = bulkDeploymentEntryRepository.getReferenceById(bulkEntryId); - entry.setState(BulkDeploymentState.PROCESSING); - bulkDeploymentEntryRepository.save(entry); + Optional<BulkDeploymentEntry> entry = bulkDeploymentEntryRepository.findById(bulkEntryId); + if(entry.isPresent()) { + BulkDeploymentEntry ent = entry.get(); + ent.setState(BulkDeploymentState.PROCESSING); + bulkDeploymentEntryRepository.save(ent); + } } @Override @@ -429,11 +434,11 @@ public class BulkApplicationServiceImpl implements BulkApplicationService { } } - private static BulkDeployment createBulkDeployment(UserViewMinimal creator) { + private BulkDeployment createBulkDeployment(UserViewMinimal creator) { BulkDeployment bulkDeployment = new BulkDeployment(); bulkDeployment.setType(BulkType.APPLICATION); bulkDeployment.setState(BulkDeploymentState.PROCESSING); - bulkDeployment.setCreatorId(creator.getId()); + bulkDeployment.setCreator(userService.findById(creator.getId()).orElseThrow(() -> new MissingElementException("User with this ID not found"))); bulkDeployment.setCreationDate(OffsetDateTime.now()); bulkDeployment.setEntries(new ArrayList<>()); return bulkDeployment; diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/BulkDomainServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/BulkDomainServiceImpl.java index 5c931595007185038b5d37254619a2b61a648870..fa2512fbd3fe755c2df5ccee00271126c5759ecb 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/BulkDomainServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/BulkDomainServiceImpl.java @@ -238,11 +238,11 @@ public class BulkDomainServiceImpl implements BulkDomainService { } } - private static BulkDeployment createBulkDeployment(UserViewMinimal creator) { + private BulkDeployment createBulkDeployment(UserViewMinimal creator) { BulkDeployment bulkDeployment = new BulkDeployment(); bulkDeployment.setType(DOMAIN); bulkDeployment.setState(PENDING); - bulkDeployment.setCreatorId(creator.getId()); + bulkDeployment.setCreator(userService.findById(creator.getId()).orElseThrow(() ->new MissingElementException("User with this ID not found"))); bulkDeployment.setCreationDate(OffsetDateTime.now()); return bulkDeployment; } diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/CustomAccessTokenServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/CustomAccessTokenServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..58bea7e30a7400dfc9ec715effd725f4f1cf8858 --- /dev/null +++ b/src/main/java/net/geant/nmaas/portal/service/impl/CustomAccessTokenServiceImpl.java @@ -0,0 +1,56 @@ +package net.geant.nmaas.portal.service.impl; + +import lombok.RequiredArgsConstructor; +import net.geant.nmaas.portal.exceptions.ObjectNotFoundException; +import net.geant.nmaas.portal.persistent.entity.AccessToken; +import net.geant.nmaas.portal.persistent.repositories.AccessTokenRepository; +import net.geant.nmaas.portal.service.CustomAccessTokenService; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.UUID; + +@Service +@RequiredArgsConstructor +public class CustomAccessTokenServiceImpl implements CustomAccessTokenService { + + private final AccessTokenRepository accessTokenRepository; + + @Override + public void invalidate(Long id) { + AccessToken token = findToken(id); + token.setValid(false); + accessTokenRepository.save(token); + } + + @Override + public AccessToken createToken(Long userId, String name) { + AccessToken token = createNewToken(userId, name); + return accessTokenRepository.save(token); + } + + @Override + public List<AccessToken> getAll(Long userId) { + return accessTokenRepository.findAllByUserId(userId); + } + + private AccessToken createNewToken(Long userId, String name) { + AccessToken token = new AccessToken(); + token.setName(name); + token.setUserId(userId); + token.setTokenValue(generateToken()); + token.setValid(true); + return token; + } + + private String generateToken() { + // uuid is a placeholder for now + return UUID.randomUUID().toString(); + } + + private AccessToken findToken(Long id) { + return accessTokenRepository + .findById(id) + .orElseThrow(() -> new ObjectNotFoundException("Could not find access token with id: " + id)); + } +} diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/DomainServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/DomainServiceImpl.java index 0caa0356871627bb0839f0bdf10545168c9701b8..98c8a5391361349d7cd86beae422d226388ce29e 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/DomainServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/DomainServiceImpl.java @@ -12,6 +12,7 @@ import net.geant.nmaas.portal.api.domain.DomainGroupView; import net.geant.nmaas.portal.api.domain.DomainRequest; import net.geant.nmaas.portal.api.domain.KeyValueView; import net.geant.nmaas.portal.api.domain.UserView; +import net.geant.nmaas.portal.api.domain.UserViewMinimal; import net.geant.nmaas.portal.api.exception.MissingElementException; import net.geant.nmaas.portal.api.exception.ProcessingException; import net.geant.nmaas.portal.events.DomainCreatedEvent; @@ -494,6 +495,24 @@ public class DomainServiceImpl implements DomainService { }); } + @Override + public DomainGroupView updateMembers(List<UserViewMinimal> newMembers, DomainGroupView view) { + //delete roles + + List<UserViewMinimal> toDeleteRole = new ArrayList<>(view.getManagers()); + toDeleteRole.removeAll(newMembers); + + toDeleteRole.forEach(user -> { + view.getDomains().forEach(domain -> { + this.removeMemberRole(domain.getId(), user.getId(), Role.ROLE_VL_DOMAIN_ADMIN); + }); + }); + + view.setManagers(newMembers); + updateRolesInDomainGroupByUsers(view); + return domainGroupService.updateDomainGroup(view.getId(), view); + } + // Domain annotations @Override diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/InternationalizationServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/InternationalizationServiceImpl.java index b114ad877816d0a6359799e971fbbd1406f3598b..bd27ed1ff631d49dc280083c18b5c336845246aa 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/InternationalizationServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/InternationalizationServiceImpl.java @@ -2,6 +2,7 @@ package net.geant.nmaas.portal.service.impl; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import net.geant.nmaas.portal.api.i18n.api.InternationalizationBriefView; import net.geant.nmaas.portal.api.i18n.api.InternationalizationView; import net.geant.nmaas.portal.persistent.entity.InternationalizationSimple; @@ -13,12 +14,16 @@ import org.modelmapper.ModelMapper; import org.springframework.stereotype.Service; import javax.transaction.Transactional; +import javax.ws.rs.NotFoundException; import java.io.IOException; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; @Service @RequiredArgsConstructor +@Slf4j public class InternationalizationServiceImpl implements InternationalizationService { private final InternationalizationSimpleRepository repository; @@ -26,9 +31,35 @@ public class InternationalizationServiceImpl implements InternationalizationServ private final ModelMapper modelMapper; @Override - public void addNewLanguage(InternationalizationView newLanguage) { + public void addNewLanguage(InternationalizationView newLanguage, Boolean force) { checkRequest(newLanguage); - repository.save(newLanguage.getAsInternationalizationSimple()); + if (repository.findByLanguageOrderByIdDesc(newLanguage.getLanguage()).isEmpty()) { + repository.save(newLanguage.getAsInternationalizationSimple()); + } else { + //add empty or override + InternationalizationSimple is = repository.findByLanguageOrderByIdDesc(newLanguage.getLanguage()).orElseThrow(() -> new NotFoundException("Language not found")); + InternationalizationView iv = is.getAsInternationalizationView(); + + if (!force) { + // only add new once, not override existed + Map<String, String> keyMap = new HashMap<>(); + is.getLanguageNodes().forEach(node -> { + keyMap.put(node.getKey(), node.getContent()); + }); + InternationalizationSimple simple = newLanguage.getAsInternationalizationSimple(); + simple.getLanguageNodes().forEach(updatedNode -> { + if (!keyMap.containsKey(updatedNode.getKey())) { + is.getLanguageNodes().add(updatedNode); + } + }); + log.debug("New added {}", simple.getLanguageNodes().size()); + repository.save(is); + } else { + //force update whole content + log.debug("force update, override all"); + updateLanguage(newLanguage.getLanguage(), newLanguage.getContent()); + } + } } private void checkRequest(InternationalizationView newLanguage) { diff --git a/src/main/resources/db/migration/common/V1.7.0_20240920_1430__addedAccessTokens.sql b/src/main/resources/db/migration/common/V1.7.0_20240920_1430__addedAccessTokens.sql new file mode 100644 index 0000000000000000000000000000000000000000..999454960500d4bfcdc76b137adea5ee0929f469 --- /dev/null +++ b/src/main/resources/db/migration/common/V1.7.0_20240920_1430__addedAccessTokens.sql @@ -0,0 +1,8 @@ +create table access_tokens ( + id bigint generated by default as identity, + name varchar(255), + token_value varchar(255), + user_id bigint, + valid boolean not null, + primary key (id) + ); \ No newline at end of file diff --git a/src/main/resources/db/migration/common/V1.7.0_20241023_1200__addContraintOnUserIdInBulkDeployment.sql b/src/main/resources/db/migration/common/V1.7.0_20241023_1200__addContraintOnUserIdInBulkDeployment.sql new file mode 100644 index 0000000000000000000000000000000000000000..df08df98f4ec98b66c4275a4c05768b983a38006 --- /dev/null +++ b/src/main/resources/db/migration/common/V1.7.0_20241023_1200__addContraintOnUserIdInBulkDeployment.sql @@ -0,0 +1,4 @@ +alter table bulk_deployment + add constraint FKqd4ff6vy2u2wu2d8aug322bc0 + foreign key (creator_id) + references users; \ No newline at end of file diff --git a/src/test/java/net/geant/nmaas/notifications/templates/TemplateServiceTest.java b/src/test/java/net/geant/nmaas/notifications/templates/TemplateServiceTest.java index ae36fb831a73d0052071e8cc385f4e68149d726a..02b79cdc8924ada64c050c8cf66a3973f52d8afc 100644 --- a/src/test/java/net/geant/nmaas/notifications/templates/TemplateServiceTest.java +++ b/src/test/java/net/geant/nmaas/notifications/templates/TemplateServiceTest.java @@ -3,6 +3,7 @@ package net.geant.nmaas.notifications.templates; import net.geant.nmaas.notifications.MailTemplateElements; import net.geant.nmaas.notifications.templates.entities.MailTemplate; import net.geant.nmaas.notifications.templates.repository.MailTemplateRepository; +import net.geant.nmaas.portal.exceptions.DataConflictException; import net.geant.nmaas.portal.service.impl.LocalFileStorageService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/src/test/java/net/geant/nmaas/notifications/types/service/FormTypeServiceTest.java b/src/test/java/net/geant/nmaas/notifications/types/service/FormTypeServiceTest.java index 2f78bed75fd4ee132402c501f071b532c37798cd..550c228e702f2e0124e3efc5f6276a9a5c33237a 100644 --- a/src/test/java/net/geant/nmaas/notifications/types/service/FormTypeServiceTest.java +++ b/src/test/java/net/geant/nmaas/notifications/types/service/FormTypeServiceTest.java @@ -4,6 +4,7 @@ import net.geant.nmaas.notifications.types.model.FormTypeRequest; import net.geant.nmaas.notifications.types.persistence.entity.FormType; import net.geant.nmaas.notifications.types.persistence.repository.FormTypeRepository; import net.geant.nmaas.portal.api.exception.ProcessingException; +import net.geant.nmaas.portal.exceptions.DataConflictException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -44,7 +45,7 @@ public class FormTypeServiceTest { when(repository.existsById(anyString())).thenReturn(true); FormTypeRequest ftr = new FormTypeRequest("CONTACT", "", "", new ArrayList<>(), ""); - assertThrows(ProcessingException.class, () -> this.underTest.create(ftr)); + assertThrows(DataConflictException.class, () -> this.underTest.create(ftr)); verify(repository, times(0)).save(any(FormType.class)); } diff --git a/src/test/java/net/geant/nmaas/portal/api/bulk/BulkControllerTest.java b/src/test/java/net/geant/nmaas/portal/api/bulk/BulkControllerTest.java index 55fe03f4842dd9763a5c08197b76685d5ab07553..02fa1407e0eaa2e1cff6860a3340007a7ef64855 100644 --- a/src/test/java/net/geant/nmaas/portal/api/bulk/BulkControllerTest.java +++ b/src/test/java/net/geant/nmaas/portal/api/bulk/BulkControllerTest.java @@ -105,7 +105,7 @@ public class BulkControllerTest { List<BulkDeployment> bulks = new ArrayList<>(); BulkDeployment viewS = new BulkDeployment(); viewS.setType(BulkType.DOMAIN); - viewS.setCreatorId(10L); + viewS.setCreator(user); bulks.add(viewS); when(bulkDeploymentRepository.findByType(BulkType.DOMAIN)).thenReturn(List.of(viewS)); assertEquals(1, Objects.requireNonNull(bulkController.getDomainDeploymentRecordsRestrictedToOwner(principalMock).getBody()).size()); @@ -126,11 +126,11 @@ public class BulkControllerTest { List<BulkDeployment> bulks = new ArrayList<>(); BulkDeployment base1 = new BulkDeployment(); base1.setType(BulkType.DOMAIN); - base1.setCreatorId(10L); + base1.setCreator(user); bulks.add(base1); BulkDeployment base2 = new BulkDeployment(); base2.setType(BulkType.DOMAIN); - base2.setCreatorId(20L); + base2.setCreator(user2); bulks.add(base2); when(bulkDeploymentRepository.findByType(BulkType.APPLICATION)).thenReturn(bulks); assertEquals(1, Objects.requireNonNull(bulkController.getAppDeploymentRecordsRestrictedToOwner(principalMock).getBody()).size()); diff --git a/src/test/java/net/geant/nmaas/portal/service/impl/ApplicationBaseServiceTest.java b/src/test/java/net/geant/nmaas/portal/service/impl/ApplicationBaseServiceTest.java index 30f8865e9d0fd7ba29d8046d6137a906373aa7dd..e62ab15033e142a87c38d3f8e1096ebe482a4ac0 100644 --- a/src/test/java/net/geant/nmaas/portal/service/impl/ApplicationBaseServiceTest.java +++ b/src/test/java/net/geant/nmaas/portal/service/impl/ApplicationBaseServiceTest.java @@ -33,7 +33,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; -public class ApplicationBaseServiceTest { +class ApplicationBaseServiceTest { private final ApplicationBase applicationBase1 = new ApplicationBase("name"); private final ApplicationBase applicationBase2 = new ApplicationBase(2L, "another"); @@ -68,7 +68,7 @@ public class ApplicationBaseServiceTest { verify(appBaseRepo, times(1)).save(any()); assertEquals(applicationBase1.getName(), result.getName()); - assertThat(result.getVersions()).hasSize(0); + assertThat(result.getVersions()).isEmpty(); } @Test diff --git a/src/test/java/net/geant/nmaas/portal/service/impl/BulkDomainServiceImplTest.java b/src/test/java/net/geant/nmaas/portal/service/impl/BulkDomainServiceImplTest.java index 1b6b7b62f2a5911e6271a3b1ce5de472881f93ed..a110e99b8e7679361cd748b47bbf24c679ea6d4c 100644 --- a/src/test/java/net/geant/nmaas/portal/service/impl/BulkDomainServiceImplTest.java +++ b/src/test/java/net/geant/nmaas/portal/service/impl/BulkDomainServiceImplTest.java @@ -66,6 +66,7 @@ public class BulkDomainServiceImplTest { when(userService.hasPrivilege((User) any(),any(),any())).thenReturn(true); when(bulkDeploymentRepository.save(any())).thenReturn(new BulkDeployment()); when(configurationManager.getConfiguration()).thenReturn(new ConfigurationView()); + when(userService.findById(any())).thenReturn(Optional.of(user)); bulkDomainService.handleBulkCreation(List.of(csvDomain), testUser()); @@ -77,7 +78,7 @@ public class BulkDomainServiceImplTest { assertEquals(2, bulkDeployment.getEntries().size()); assertThat(bulkDeployment.getEntries().stream().filter(e -> e.getType() == BulkType.USER).findAny().orElseThrow().getCreated()).isFalse(); assertThat(bulkDeployment.getEntries().stream().filter(e -> e.getType() == BulkType.DOMAIN).findAny().orElseThrow().getCreated()).isFalse(); - assertEquals(testUser().getId(), bulkDeployment.getCreatorId()); + assertEquals(testUser().getId(), bulkDeployment.getCreator().getId()); } @Test @@ -99,6 +100,7 @@ public class BulkDomainServiceImplTest { when(userService.hasPrivilege((User) any(),any(),any())).thenReturn(true); when(bulkDeploymentRepository.save(any())).thenReturn(new BulkDeployment()); when(configurationManager.getConfiguration()).thenReturn(new ConfigurationView()); + when(userService.findById(any())).thenReturn(Optional.of(user)); bulkDomainService.handleBulkCreation(List.of(csvDomain), testUser()); @@ -110,7 +112,7 @@ public class BulkDomainServiceImplTest { assertEquals(2, bulkDeployment.getEntries().size()); assertThat(bulkDeployment.getEntries().stream().filter(e -> e.getType() == BulkType.USER).findAny().orElseThrow().getCreated()).isFalse(); assertThat(bulkDeployment.getEntries().stream().filter(e -> e.getType() == BulkType.DOMAIN).findAny().orElseThrow().getCreated()).isTrue(); - assertEquals(testUser().getId(), bulkDeployment.getCreatorId()); + assertEquals(testUser().getId(), bulkDeployment.getCreator().getId()); } @Test @@ -131,10 +133,11 @@ public class BulkDomainServiceImplTest { when(userService.existsByUsername("user2")).thenReturn(false); when(userService.existsByEmail("user2@test.com")).thenReturn(Boolean.FALSE); User user = new User("user1", true); - user.setId(10L); + user.setId(1L); user.setEmail("user1@test.com"); when(userService.registerBulk(any(), any(), any())).thenReturn(user); when(bulkDeploymentRepository.save(any())).thenReturn(new BulkDeployment()); + when(userService.findById(any())).thenReturn(Optional.of(user)); bulkDomainService.handleBulkCreation(List.of(csvDomain1, csvDomain2), testUser()); @@ -146,7 +149,7 @@ public class BulkDomainServiceImplTest { assertEquals(4, bulkDeployment.getEntries().size()); assertThat(bulkDeployment.getEntries().stream().filter(e -> e.getType() == BulkType.USER)).allMatch(BulkDeploymentEntry::getCreated); assertThat(bulkDeployment.getEntries().stream().filter(e -> e.getType() == BulkType.DOMAIN)).noneMatch(BulkDeploymentEntry::getCreated); - assertEquals(testUser().getId(), bulkDeployment.getCreatorId()); + assertEquals(testUser().getId(), bulkDeployment.getCreator().getId()); } private static UserViewMinimal testUser() { diff --git a/src/test/java/net/geant/nmaas/portal/service/impl/DomainServiceTest.java b/src/test/java/net/geant/nmaas/portal/service/impl/DomainServiceTest.java index e9e2e9922bb914f33c467d751f6318fca83e33d1..c997d0800980ffcbef7e211ffe0472e7cfec74a6 100644 --- a/src/test/java/net/geant/nmaas/portal/service/impl/DomainServiceTest.java +++ b/src/test/java/net/geant/nmaas/portal/service/impl/DomainServiceTest.java @@ -1,6 +1,5 @@ package net.geant.nmaas.portal.service.impl; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import net.geant.nmaas.dcn.deployment.DcnDeploymentType; import net.geant.nmaas.dcn.deployment.DcnRepositoryManager; @@ -8,10 +7,13 @@ import net.geant.nmaas.dcn.deployment.entities.DomainDcnDetails; import net.geant.nmaas.dcn.deployment.repositories.DomainDcnDetailsRepository; import net.geant.nmaas.orchestration.entities.DomainTechDetails; import net.geant.nmaas.orchestration.repositories.DomainTechDetailsRepository; +import net.geant.nmaas.portal.api.domain.DomainBase; import net.geant.nmaas.portal.api.domain.DomainDcnDetailsView; +import net.geant.nmaas.portal.api.domain.DomainGroupView; import net.geant.nmaas.portal.api.domain.DomainRequest; import net.geant.nmaas.portal.api.domain.DomainTechDetailsView; import net.geant.nmaas.portal.api.domain.UserView; +import net.geant.nmaas.portal.api.domain.UserViewMinimal; import net.geant.nmaas.portal.api.exception.ProcessingException; import net.geant.nmaas.portal.events.DomainCreatedEvent; import net.geant.nmaas.portal.persistent.entity.ApplicationBase; @@ -55,7 +57,7 @@ import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import static org.mockito.internal.verification.VerificationModeFactory.times; -public class DomainServiceTest { +class DomainServiceTest { DomainServiceImpl.CodenameValidator validator; DomainServiceImpl.CodenameValidator namespaceValidator; @@ -246,7 +248,9 @@ public class DomainServiceTest { when(userRoleRepo.findByDomainAndUserAndRole(domain, user, role)).thenReturn(null); when(userService.findById(userId)).thenReturn(Optional.of(user)); when(domainRepository.findById(domainId)).thenReturn(Optional.of(domain)); - this.domainService.addMemberRole(domainId, userId, role); + + domainService.addMemberRole(domainId, userId, role); + verify(userRoleRepo, times(1)).save(any()); } @@ -379,12 +383,12 @@ public class DomainServiceTest { Domain domain = new Domain(1L, "testdom", "testdom"); User user1 = new User("user1"); - user1.setRoles(ImmutableList.of(new UserRole(user1, domain, Role.ROLE_DOMAIN_ADMIN), new UserRole(user1, domain, Role.ROLE_OPERATOR))); + user1.setRoles(List.of(new UserRole(user1, domain, Role.ROLE_DOMAIN_ADMIN), new UserRole(user1, domain, Role.ROLE_OPERATOR))); User user2 = new User("user2"); - user2.setRoles(ImmutableList.of(new UserRole(user2, domain, Role.ROLE_DOMAIN_ADMIN))); + user2.setRoles(List.of(new UserRole(user2, domain, Role.ROLE_DOMAIN_ADMIN))); - List<User> users = ImmutableList.of(user1, user2); + List<User> users = List.of(user1, user2); when(userRoleRepo.findDomainMembers(anyString())).thenReturn(users); List<UserView> filteredUsers = domainService.findUsersWithDomainAdminRole(domain.getCodename()); assertThat("Result mismatch", filteredUsers.size() == 2); @@ -487,8 +491,95 @@ public class DomainServiceTest { assertEquals(0, domainGroup.getApplicationStatePerDomain().size()); assertEquals(0, domainGroup2.getApplicationStatePerDomain().size()); + } + + @Test + void shouldChangeMembersFromGroupView() { + DomainBase domain1 = new DomainBase(); + domain1.setId(1L); + domain1.setName("dom1"); + domain1.setCodename("dom1"); + Domain domain = new Domain(1L,"dom1", "dom1"); + + when(domainRepository.findById(1L)).thenReturn(Optional.of(domain)); + when(userService.findById(1L)).thenReturn(Optional.of(new User("test"))); + when(userService.findById(2L)).thenReturn(Optional.of(new User("test2"))); + + UserViewMinimal userView = new UserViewMinimal(); + userView.setId(1L); + + UserViewMinimal userView2 = new UserViewMinimal(); + userView2.setId(2L); + DomainGroupView domainGroupView = new DomainGroupView(1L, "test", "test1", List.of(domain1), null, List.of(userView) ); + + User user = new User("user"); + DomainGroup domainGroup = new DomainGroup(1L, "test", "test1"); + domainGroup.setManagers(List.of(user)); + + when(domainGroupRepository.findById(1L)).thenReturn(Optional.of(domainGroup)); + + DomainGroupView result = domainService.updateMembers(List.of(userView2), domainGroupView ); + + assertEquals(1, result.getManagers().size()); + assertEquals(2L , result.getManagers().get(0).getId()); + } + + @Test + void shouldAddMembersFromGroupView() { + DomainBase domain1 = new DomainBase(); + domain1.setId(1L); + domain1.setName("dom1"); + domain1.setCodename("dom1"); + Domain domain = new Domain(1L,"dom1", "dom1"); + + when(domainRepository.findById(1L)).thenReturn(Optional.of(domain)); + when(userService.findById(1L)).thenReturn(Optional.of(new User("test"))); + when(userService.findById(2L)).thenReturn(Optional.of(new User("test2"))); + + UserViewMinimal userView = new UserViewMinimal(); + userView.setId(1L); + + UserViewMinimal userView2 = new UserViewMinimal(); + userView2.setId(2L); + + DomainGroupView domainGroupView = new DomainGroupView(1L, "test", "test1",List.of(domain1), null, List.of(userView) ); + User user = new User("user"); + DomainGroup domainGroup = new DomainGroup(1L, "test", "test1"); + domainGroup.setManagers(List.of(user)); + when(domainGroupRepository.findById(1L)).thenReturn(Optional.of(domainGroup)); + + DomainGroupView result = domainService.updateMembers(List.of(userView2, userView), domainGroupView ); + + assertEquals(2, result.getManagers().size()); + } + + @Test + void shouldDeleteMembersFromGroupView() { + DomainBase domain1 = new DomainBase(); + domain1.setId(1L); + domain1.setName("dom1"); + domain1.setCodename("dom1"); + Domain domain = new Domain(1L,"dom1", "dom1"); + + when(domainRepository.findById(1L)).thenReturn(Optional.of(domain)); + when(userService.findById(1L)).thenReturn(Optional.of(new User("test"))); + when(userService.findById(2L)).thenReturn(Optional.of(new User("test2"))); + + UserViewMinimal userView = new UserViewMinimal(); + userView.setId(1L); + + UserViewMinimal userView2 = new UserViewMinimal(); + userView2.setId(2L); + + DomainGroupView domainGroupView = new DomainGroupView(1L, "test", "test1",List.of(domain1), null, List.of(userView) ); + User user = new User("user"); + DomainGroup domainGroup = new DomainGroup(1L, "test", "test1"); + domainGroup.setManagers(List.of(user)); + when(domainGroupRepository.findById(1L)).thenReturn(Optional.of(domainGroup)); + DomainGroupView result = domainService.updateMembers(List.of(), domainGroupView ); + assertEquals(0, result.getManagers().size()); } } diff --git a/src/test/java/net/geant/nmaas/portal/service/impl/SSHKeyServiceTest.java b/src/test/java/net/geant/nmaas/portal/service/impl/SSHKeyServiceTest.java index 09ff0e37dfd01e8dd0898a6b61c59f56f56b6a0e..fbf9baf42ec847be5e209e0acf3178e587aa99fb 100644 --- a/src/test/java/net/geant/nmaas/portal/service/impl/SSHKeyServiceTest.java +++ b/src/test/java/net/geant/nmaas/portal/service/impl/SSHKeyServiceTest.java @@ -6,8 +6,8 @@ import net.geant.nmaas.portal.persistent.entity.SSHKeyEntity; import net.geant.nmaas.portal.persistent.entity.User; import net.geant.nmaas.portal.persistent.repositories.SSHKeyRepository; import net.geant.nmaas.portal.service.SSHKeyService; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationEventPublisher; import java.util.ArrayList; @@ -17,20 +17,22 @@ import java.util.Optional; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; -public class SSHKeyServiceTest { +class SSHKeyServiceTest { private final SSHKeyRepository repository = mock(SSHKeyRepository.class); - private final ApplicationEventPublisher eventPublisher = mock(ApplicationEventPublisher.class); private SSHKeyService sut; - private User owner; @BeforeEach - public void setup() { + void setup() { this.owner = new User("owner"); this.owner.setId(1L); SSHKeyEntity key = new SSHKeyEntity(owner, "name", "key long long long"); @@ -44,7 +46,7 @@ public class SSHKeyServiceTest { } @Test - public void ShouldReturnAllKeysForUser() { + void ShouldReturnAllKeysForUser() { List<SSHKeyView> result = this.sut.findAllByUser(this.owner); assertEquals(1, result.size()); @@ -52,15 +54,14 @@ public class SSHKeyServiceTest { } @Test - public void shouldDeleteKeyIfValidRequest() { - + void shouldDeleteKeyIfValidRequest() { this.sut.invalidate(this.owner, 1L); verify(this.repository, times(1)).deleteById(1L); } @Test - public void shouldThrowExceptionWhenKeyDoesNotExist() { + void shouldThrowExceptionWhenKeyDoesNotExist() { IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> { this.sut.invalidate(this.owner, 2L); }); @@ -69,7 +70,7 @@ public class SSHKeyServiceTest { } @Test - public void shouldThrowExceptionWhenKeyDoesNotBelongToTheUser() { + void shouldThrowExceptionWhenKeyDoesNotBelongToTheUser() { User anonymous = new User("anonymous"); anonymous.setId(31L); IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> { @@ -77,11 +78,10 @@ public class SSHKeyServiceTest { }); assertEquals("Invalid key owner", e.getMessage()); - } @Test - public void shouldCreateNewSSHKeyEntityWhenNameValid() { + void shouldCreateNewSSHKeyEntityWhenNameValid() { when(repository.existsByOwnerAndName(this.owner, "new key")).thenReturn(false); SSHKeyRequest request = new SSHKeyRequest("new key", "so long key"); SSHKeyEntity res = new SSHKeyEntity(owner, "new key", "so long key"); @@ -96,7 +96,7 @@ public class SSHKeyServiceTest { } @Test - public void shouldThrowExceptionWhenNameIsNotUnique() { + void shouldThrowExceptionWhenNameIsNotUnique() { when(repository.existsByOwnerAndName(this.owner, "name")).thenReturn(true); SSHKeyRequest request = new SSHKeyRequest("name", "so long key"); @@ -106,4 +106,5 @@ public class SSHKeyServiceTest { assertEquals("Name is already taken", e.getMessage()); } + } diff --git a/src/test/shell/data/i18n/de.json b/src/test/shell/data/i18n/de.json index d5214b14ab79b863fd69cbf43f54b49561bfabb1..1d2b7ced244d0fd8fca3a57e5f3d2c070177b8dc 100644 --- a/src/test/shell/data/i18n/de.json +++ b/src/test/shell/data/i18n/de.json @@ -1171,6 +1171,30 @@ } } }, + "TOKENS": { + "HEADER": "Tokens", + "TABLE": { + "ID": "ID", + "NAME": "Name", + "VALUE": "Value", + "VALID": "Valid", + "ACTIONS": "Actions" + }, + "MODAL": { + "HEADER": "Add new access token", + "NAME": "Name", + "BUTTON_ADD": "Submit", + "BUTTON_CANCEL": "Cancel", + "ERROR": { + "NAME_REQUIRED": "Name is required", + "NAME_MINLENGTH": "Name must have at least 1 character", + "NAME_MAXLENGTH": "Name cannot be longer than 16 characters" + } + }, + "BUTTON_INVALIDATE": "Invalidate", + "NO_TOKENS": "No tokens", + "NEW_TOKEN": "Add new token" + }, "JSON_EDIT": { "INVALID_JSON": "Invalid JSON format. Changes made to the content of the wizard will not be persisted." }, diff --git a/src/test/shell/data/i18n/en.json b/src/test/shell/data/i18n/en.json index da4edbfb3c1489269a8e21b9eefdb6c46f0396e7..ca170d950606da76a4567ca8ba6955517428f5b9 100644 --- a/src/test/shell/data/i18n/en.json +++ b/src/test/shell/data/i18n/en.json @@ -1172,6 +1172,30 @@ } } }, + "TOKENS": { + "HEADER": "Tokens", + "TABLE": { + "ID": "ID", + "NAME": "Name", + "VALUE": "Value", + "VALID": "Valid", + "ACTIONS": "Actions" + }, + "MODAL": { + "HEADER": "Add new access token", + "NAME": "Name", + "BUTTON_ADD": "Submit", + "BUTTON_CANCEL": "Cancel", + "ERROR": { + "NAME_REQUIRED": "Name is required", + "NAME_MINLENGTH": "Name must have at least 1 character", + "NAME_MAXLENGTH": "Name cannot be longer than 16 characters" + } + }, + "BUTTON_INVALIDATE": "Invalidate", + "NO_TOKENS": "No tokens", + "NEW_TOKEN": "Add new token" + }, "JSON_EDIT": { "INVALID_JSON": "Invalid JSON format. Changes made to the content of the wizard will not be persisted." }, diff --git a/src/test/shell/data/i18n/fr.json b/src/test/shell/data/i18n/fr.json index 1ea6be4e2858fc1def457257105a851889bbcf41..77eb1a955ef5bd58f41030c0e05588c08b8fef35 100644 --- a/src/test/shell/data/i18n/fr.json +++ b/src/test/shell/data/i18n/fr.json @@ -1172,6 +1172,30 @@ } } }, + "TOKENS": { + "HEADER": "Tokens", + "TABLE": { + "ID": "ID", + "NAME": "Name", + "VALUE": "Value", + "VALID": "Valid", + "ACTIONS": "Actions" + }, + "MODAL": { + "HEADER": "Add new access token", + "NAME": "Name", + "BUTTON_ADD": "Submit", + "BUTTON_CANCEL": "Cancel", + "ERROR": { + "NAME_REQUIRED": "Name is required", + "NAME_MINLENGTH": "Name must have at least 1 character", + "NAME_MAXLENGTH": "Name cannot be longer than 16 characters" + } + }, + "BUTTON_INVALIDATE": "Invalidate", + "NO_TOKENS": "No tokens", + "NEW_TOKEN": "Add new token" + }, "JSON_EDIT": { "INVALID_JSON": "Invalid JSON format. Changes made to the content of the wizard will not be persisted." }, diff --git a/src/test/shell/data/i18n/pl.json b/src/test/shell/data/i18n/pl.json index e36774e852318adee4b558235f24644949e9a941..422adc5baf045bf8fc92086789d6c34a346721c1 100644 --- a/src/test/shell/data/i18n/pl.json +++ b/src/test/shell/data/i18n/pl.json @@ -1172,6 +1172,30 @@ } } }, + "TOKENS": { + "HEADER": "Tokens", + "TABLE": { + "ID": "ID", + "NAME": "Name", + "VALUE": "Value", + "VALID": "Valid", + "ACTIONS": "Actions" + }, + "MODAL": { + "HEADER": "Add new access token", + "NAME": "Name", + "BUTTON_ADD": "Submit", + "BUTTON_CANCEL": "Cancel", + "ERROR": { + "NAME_REQUIRED": "Name is required", + "NAME_MINLENGTH": "Name must have at least 1 character", + "NAME_MAXLENGTH": "Name cannot be longer than 16 characters" + } + }, + "BUTTON_INVALIDATE": "Invalidate", + "NO_TOKENS": "No tokens", + "NEW_TOKEN": "Add new token" + }, "JSON_EDIT": { "INVALID_JSON": "Niewłaściwy format JSON. Zmiany wprowadzone do zawartości formularza nie zostaną zapisane." }, @@ -1231,8 +1255,7 @@ "CHECK_STATE" : "Sprawdź status", "UPLOAD_TEXT" : "lub podaj tekst w formacie CSV poniżej", "DOWNLOAD_CSV" : "Pobierz CSV", - "REFRESH" : "Odśwież status " - + "REFRESH" : "Odśwież stany" }, "STATE" : { "PENDING" : "Oczekuje",