From 8e703d81fe2e26ffa0f57d13ce5ecd651b0d3511 Mon Sep 17 00:00:00 2001 From: pgiertych <pgiertych@man.poznan.pl> Date: Tue, 12 Mar 2024 13:02:05 +0100 Subject: [PATCH 01/50] added endpoint for bulk deployment removal --- .../nmaas/portal/api/bulk/BulkController.java | 53 +++++++++++++------ .../service/BulkApplicationService.java | 4 +- .../impl/BulkApplicationServiceImpl.java | 25 ++++++++- src/test/shell/data/i18n/de.json | 5 +- src/test/shell/data/i18n/en.json | 5 +- src/test/shell/data/i18n/fr.json | 5 +- src/test/shell/data/i18n/pl.json | 5 +- 7 files changed, 74 insertions(+), 28 deletions(-) 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 c42118894..df2fd49cc 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 @@ -17,6 +17,7 @@ import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -30,6 +31,7 @@ import java.security.Principal; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; @RestController @@ -91,17 +93,14 @@ public class BulkController { @GetMapping @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN')") public ResponseEntity<List<BulkDeploymentViewS>> getAllDeploymentRecords() { - return ResponseEntity.ok(mapToView(bulkDeploymentRepository.findAll())); + return ResponseEntity.ok(mapToViewList(bulkDeploymentRepository.findAll())); } @GetMapping("/{id}") @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN') || hasRole('ROLE_VL_MANAGER')") public ResponseEntity<BulkDeploymentView> getDeploymentRecord(@PathVariable Long id) { BulkDeployment bulk = bulkDeploymentRepository.findById(id).orElseThrow(); - BulkDeploymentView bulkView = modelMapper.map(bulk, BulkDeploymentView.class); - bulkView.setCreator(getUserView(bulk.getCreatorId())); - mapDetails(bulk, bulkView); - return ResponseEntity.ok(bulkView); + return ResponseEntity.ok(mapToView(bulk, BulkDeploymentView.class)); } @GetMapping(value = "/app/csv/{id}", produces = "text/csv") @@ -124,7 +123,7 @@ public class BulkController { @GetMapping("/domains") @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN')") public ResponseEntity<List<BulkDeploymentViewS>> getDomainDeploymentRecords() { - return ResponseEntity.ok(mapToView(bulkDeploymentRepository.findByType(BulkType.DOMAIN))); + return ResponseEntity.ok(mapToViewList(bulkDeploymentRepository.findByType(BulkType.DOMAIN))); } @GetMapping("/domains/vl") @@ -132,14 +131,14 @@ public class BulkController { public ResponseEntity<List<BulkDeploymentViewS>> getDomainDeploymentRecordsRestrictedToOwner(Principal principal) { User user = this.userService.findByUsername(principal.getName()).orElseThrow(() -> new MissingElementException("Missing user " + principal.getName())); - return ResponseEntity.ok(mapToView(bulkDeploymentRepository.findByType(BulkType.DOMAIN)).stream() - .filter(bulk -> bulk.getCreator().getId().equals(user.getId())).collect(Collectors.toList())); + return ResponseEntity.ok(mapToViewList(bulkDeploymentRepository.findByType(BulkType.DOMAIN)).stream() + .filter(bulk -> bulk.getCreator().getId().equals(user.getId())).collect(Collectors.toList())); } @GetMapping("/apps") @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN')") public ResponseEntity<List<BulkDeploymentViewS>> getAppDeploymentRecords() { - return ResponseEntity.ok(mapToView(bulkDeploymentRepository.findByType(BulkType.APPLICATION))); + return ResponseEntity.ok(mapToViewList(bulkDeploymentRepository.findByType(BulkType.APPLICATION))); } @GetMapping("/apps/vl") @@ -147,21 +146,41 @@ public class BulkController { public ResponseEntity<List<BulkDeploymentViewS>> getAppDeploymentRecordsRestrictedToOwner(Principal principal) { User user = this.userService.findByUsername(principal.getName()).orElseThrow(() -> new MissingElementException("Missing user " + principal.getName())); - return ResponseEntity.ok(mapToView(bulkDeploymentRepository.findByType(BulkType.APPLICATION)).stream() + return ResponseEntity.ok(mapToViewList(bulkDeploymentRepository.findByType(BulkType.APPLICATION)).stream() .filter(bulk -> bulk.getCreator().getId().equals(user.getId())).collect(Collectors.toList())); } - private List<BulkDeploymentViewS> mapToView(List<BulkDeployment> deployments) { + @DeleteMapping("/{id}") + @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN')") + public ResponseEntity<Void> removeBulkDeployment( + @PathVariable Long id, + @RequestParam(name = "removeAll") boolean removeApps + ) { + + Optional<BulkDeployment> bulk = this.bulkDeploymentRepository.findById(id); + if (bulk.isEmpty()) { + return ResponseEntity.notFound().build(); + } + if (removeApps) { + bulkApplicationService.deleteAppInstancesFromBulk(mapToView(bulk.get(), BulkDeploymentView.class)); + } + bulkDeploymentRepository.delete(bulk.get()); + return ResponseEntity.ok().build(); + } + + private List<BulkDeploymentViewS> mapToViewList(List<BulkDeployment> deployments) { return deployments.stream() - .map(bulk -> { - BulkDeploymentViewS bulkView = modelMapper.map(bulk, BulkDeploymentViewS.class); - bulkView.setCreator(getUserView(bulk.getCreatorId())); - mapDetails(bulk, bulkView); - return bulkView; - }) + .map(bulk -> mapToView(bulk, BulkDeploymentViewS.class)) .collect(Collectors.toList()); } + private <T extends BulkDeploymentViewS> T mapToView(BulkDeployment bulk, Class<T> viewType) { + T bulkView = modelMapper.map(bulk, viewType); + bulkView.setCreator(getUserView(bulk.getCreatorId())); + mapDetails(bulk, bulkView); + return bulkView; + } + private void mapDetails(BulkDeployment deployment, BulkDeploymentViewS view) { if (deployment.getType().equals(BulkType.APPLICATION)) { Map<String, String> details = new HashMap<>(); 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 bebf1c9f8..656dcd11d 100644 --- a/src/main/java/net/geant/nmaas/portal/service/BulkApplicationService.java +++ b/src/main/java/net/geant/nmaas/portal/service/BulkApplicationService.java @@ -22,6 +22,8 @@ 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/impl/BulkApplicationServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/BulkApplicationServiceImpl.java index aea95a4ed..34ea8b171 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 @@ -14,6 +14,7 @@ import net.geant.nmaas.orchestration.events.app.AppAutoDeploymentReviewEvent; import net.geant.nmaas.orchestration.events.app.AppAutoDeploymentStatusUpdateEvent; import net.geant.nmaas.orchestration.events.app.AppAutoDeploymentTriggeredEvent; import net.geant.nmaas.portal.api.bulk.BulkAppDetails; +import net.geant.nmaas.portal.api.bulk.BulkDeploymentEntryView; import net.geant.nmaas.portal.api.bulk.BulkDeploymentView; import net.geant.nmaas.portal.api.bulk.BulkDeploymentViewS; import net.geant.nmaas.portal.api.bulk.BulkType; @@ -21,6 +22,7 @@ import net.geant.nmaas.portal.api.bulk.CsvApplication; import net.geant.nmaas.portal.api.domain.AppInstanceState; import net.geant.nmaas.portal.api.domain.UserViewMinimal; import net.geant.nmaas.portal.api.exception.MissingElementException; +import net.geant.nmaas.portal.exceptions.ObjectNotFoundException; import net.geant.nmaas.portal.persistent.entity.AppInstance; import net.geant.nmaas.portal.persistent.entity.Application; import net.geant.nmaas.portal.persistent.entity.BulkDeployment; @@ -55,6 +57,7 @@ import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -300,6 +303,24 @@ public class BulkApplicationServiceImpl implements BulkApplicationService { ); } + @Override + public void deleteAppInstancesFromBulk(BulkDeploymentView bulk) { + List<BulkDeploymentEntryView> apps = bulk.getEntries(); + for (BulkDeploymentEntryView app : apps) { + Long appInstanceId = Long.valueOf(findAppDetail(app, BULK_ENTRY_DETAIL_KEY_APP_INSTANCE_ID)); + AppInstance appInstance = instanceService.find(appInstanceId) + .orElseThrow(() -> new ObjectNotFoundException("Domain not found")); + + appLifecycleManager.removeApplication(appInstance.getInternalId()); + instanceService.delete(appInstanceId); + } + } + + private String findAppDetail(BulkDeploymentEntryView app, String key) { + return Optional.ofNullable(app.getDetails().get(key)) + .orElseThrow(() -> new ObjectNotFoundException(key + " not found")); + } + private static BulkDeployment createBulkDeployment(UserViewMinimal creator) { BulkDeployment bulkDeployment = new BulkDeployment(); bulkDeployment.setType(BulkType.APPLICATION); @@ -355,8 +376,8 @@ public class BulkApplicationServiceImpl implements BulkApplicationService { //deploy Map<String, String> params = appDeploymentMonitor.appDeploymentParameters(instance.getInternalId()); - params.forEach( (key, value) -> { - configurationParameters.put(key, Objects.isNull(value) || Objects.equals(value, "") ? EMPTY_VALUE : value.replace("\"", "")); + params.forEach((key, value) -> { + configurationParameters.put(key, Objects.isNull(value) || Objects.equals(value, "") ? EMPTY_VALUE : value.replace("\"", "")); log.debug("Params = {} - {}", key, value); }); diff --git a/src/test/shell/data/i18n/de.json b/src/test/shell/data/i18n/de.json index 6d0b19d12..b1508c109 100644 --- a/src/test/shell/data/i18n/de.json +++ b/src/test/shell/data/i18n/de.json @@ -1219,8 +1219,9 @@ }, "REMOVE" : { "HEADER" : "Remove bulk deployment", - "APP" : "Do you want to remove all instances created by this bulk ? ", - "REMOVE" : "Remove" + "APP" : "Do you want to remove all instances created by this bulk deployment?", + "REMOVE" : "Remove", + "ERROR": "Error removing bulk deployment:" } }, "SHARED" : { diff --git a/src/test/shell/data/i18n/en.json b/src/test/shell/data/i18n/en.json index db0f617fa..a0f291875 100644 --- a/src/test/shell/data/i18n/en.json +++ b/src/test/shell/data/i18n/en.json @@ -1223,8 +1223,9 @@ }, "REMOVE" : { "HEADER" : "Remove bulk deployment", - "APP" : "Do you want to remove all instances created by this bulk ? ", - "REMOVE" : "Remove" + "APP" : "Do you want to remove all instances created by this bulk deployment?", + "REMOVE" : "Remove", + "ERROR": "Error removing bulk deployment:" } }, "SHARED" : { diff --git a/src/test/shell/data/i18n/fr.json b/src/test/shell/data/i18n/fr.json index 2efa5331d..55338e03d 100644 --- a/src/test/shell/data/i18n/fr.json +++ b/src/test/shell/data/i18n/fr.json @@ -1219,8 +1219,9 @@ }, "REMOVE" : { "HEADER" : "Remove bulk deployment", - "APP" : "Do you want to remove all instances created by this bulk ? ", - "REMOVE" : "Remove" + "APP" : "Do you want to remove all instances created by this bulk deployment?", + "REMOVE" : "Remove", + "ERROR": "Error removing bulk deployment:" } }, "SHARED" : { diff --git a/src/test/shell/data/i18n/pl.json b/src/test/shell/data/i18n/pl.json index 992805e42..251a54ee5 100644 --- a/src/test/shell/data/i18n/pl.json +++ b/src/test/shell/data/i18n/pl.json @@ -1221,8 +1221,9 @@ }, "REMOVE" : { "HEADER" : "Remove bulk deployment", - "APP" : "Do you want to remove all instances created by this bulk ? ", - "REMOVE" : "Remove" + "APP" : "Do you want to remove all instances created by this bulk deployment?", + "REMOVE" : "Remove", + "ERROR": "Error removing bulk deployment:" } }, "SHARED" : { -- GitLab From e657128d1ccea5d9695e2ee8c0b4374225a8f0c3 Mon Sep 17 00:00:00 2001 From: pgiertych <pgiertych@man.poznan.pl> Date: Tue, 12 Mar 2024 13:06:50 +0100 Subject: [PATCH 02/50] change error message --- .../nmaas/portal/service/impl/BulkApplicationServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 34ea8b171..8efe9388d 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 @@ -309,7 +309,7 @@ public class BulkApplicationServiceImpl implements BulkApplicationService { for (BulkDeploymentEntryView app : apps) { Long appInstanceId = Long.valueOf(findAppDetail(app, BULK_ENTRY_DETAIL_KEY_APP_INSTANCE_ID)); AppInstance appInstance = instanceService.find(appInstanceId) - .orElseThrow(() -> new ObjectNotFoundException("Domain not found")); + .orElseThrow(() -> new ObjectNotFoundException("App instance not found")); appLifecycleManager.removeApplication(appInstance.getInternalId()); instanceService.delete(appInstanceId); -- GitLab From 36d1f85ee936cd4a623253755a2de75ecd6e8767 Mon Sep 17 00:00:00 2001 From: pgiertych <pgiertych@man.poznan.pl> Date: Wed, 10 Apr 2024 14:08:41 +0200 Subject: [PATCH 03/50] token management --- .../security/CustomAccessTokenController.java | 58 +++++++++++++++++++ .../portal/persistent/entity/AccessToken.java | 31 ++++++++++ .../repositories/AccessTokenRepository.java | 12 ++++ .../service/CustomAccessTokenService.java | 13 +++++ .../impl/CustomAccessTokenServiceImpl.java | 54 +++++++++++++++++ src/test/shell/data/i18n/de.json | 12 ++++ src/test/shell/data/i18n/en.json | 12 ++++ src/test/shell/data/i18n/fr.json | 12 ++++ src/test/shell/data/i18n/pl.json | 12 ++++ 9 files changed, 216 insertions(+) create mode 100644 src/main/java/net/geant/nmaas/portal/api/security/CustomAccessTokenController.java create mode 100644 src/main/java/net/geant/nmaas/portal/persistent/entity/AccessToken.java create mode 100644 src/main/java/net/geant/nmaas/portal/persistent/repositories/AccessTokenRepository.java create mode 100644 src/main/java/net/geant/nmaas/portal/service/CustomAccessTokenService.java create mode 100644 src/main/java/net/geant/nmaas/portal/service/impl/CustomAccessTokenServiceImpl.java 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 000000000..1a7d19a72 --- /dev/null +++ b/src/main/java/net/geant/nmaas/portal/api/security/CustomAccessTokenController.java @@ -0,0 +1,58 @@ +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.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) { + User user = getUser(principal); + return accessTokenService.createToken(user.getId()); + } + + @PutMapping("/{id}") + public void invalidateToken(@PathVariable Long id) { + accessTokenService.invalidate(id); + } + + @GetMapping("/test") + public String testSecurity() { + return "works"; + } + + + + 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/persistent/entity/AccessToken.java b/src/main/java/net/geant/nmaas/portal/persistent/entity/AccessToken.java new file mode 100644 index 000000000..2cf56de55 --- /dev/null +++ b/src/main/java/net/geant/nmaas/portal/persistent/entity/AccessToken.java @@ -0,0 +1,31 @@ +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 = "accessTokens") +@NoArgsConstructor +@Getter +@Setter +@AllArgsConstructor +public class AccessToken { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private Long userId; + + private String tokenValue; + + private boolean valid; +} 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 000000000..7655ad0af --- /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/service/CustomAccessTokenService.java b/src/main/java/net/geant/nmaas/portal/service/CustomAccessTokenService.java new file mode 100644 index 000000000..5ba1a2268 --- /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); + List<AccessToken> getAll(Long userId); + +} 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 000000000..90b0cf5ff --- /dev/null +++ b/src/main/java/net/geant/nmaas/portal/service/impl/CustomAccessTokenServiceImpl.java @@ -0,0 +1,54 @@ +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) { + AccessToken token = createNewToken(userId); + return accessTokenRepository.save(token); + } + + @Override + public List<AccessToken> getAll(Long userId) { + return accessTokenRepository.findAllByUserId(userId); + } + + private AccessToken createNewToken(Long userId) { + AccessToken token = new AccessToken(); + token.setUserId(userId); + token.setTokenValue(generateToken()); + token.setValid(true); + return token; + } + + private String generateToken() { + 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/test/shell/data/i18n/de.json b/src/test/shell/data/i18n/de.json index 6d0b19d12..3239b4c99 100644 --- a/src/test/shell/data/i18n/de.json +++ b/src/test/shell/data/i18n/de.json @@ -1151,6 +1151,18 @@ } } }, + "TOKENS": { + "HEADER": "Tokens", + "TABLE": { + "ID": "ID", + "VALUE": "Value", + "VALID": "Valid", + "ACTIONS": "Actions" + }, + "BUTTON_INVALIDATE": "Invalidate", + "NO_TOKENS": "No tokens", + "NEW_TOKEN": "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 db0f617fa..8a1ce458e 100644 --- a/src/test/shell/data/i18n/en.json +++ b/src/test/shell/data/i18n/en.json @@ -1153,6 +1153,18 @@ } } }, + "TOKENS": { + "HEADER": "Tokens", + "TABLE": { + "ID": "ID", + "VALUE": "Value", + "VALID": "Valid", + "ACTIONS": "Actions" + }, + "BUTTON_INVALIDATE": "Invalidate", + "NO_TOKENS": "No tokens", + "NEW_TOKEN": "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 2efa5331d..7a1470747 100644 --- a/src/test/shell/data/i18n/fr.json +++ b/src/test/shell/data/i18n/fr.json @@ -1151,6 +1151,18 @@ } } }, + "TOKENS": { + "HEADER": "Tokens", + "TABLE": { + "ID": "ID", + "VALUE": "Value", + "VALID": "Valid", + "ACTIONS": "Actions" + }, + "BUTTON_INVALIDATE": "Invalidate", + "NO_TOKENS": "No tokens", + "NEW_TOKEN": "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 992805e42..25f8a91e0 100644 --- a/src/test/shell/data/i18n/pl.json +++ b/src/test/shell/data/i18n/pl.json @@ -1152,6 +1152,18 @@ } } }, + "TOKENS": { + "HEADER": "Tokens", + "TABLE": { + "ID": "ID", + "VALUE": "Value", + "VALID": "Valid", + "ACTIONS": "Actions" + }, + "BUTTON_INVALIDATE": "Invalidate", + "NO_TOKENS": "No tokens", + "NEW_TOKEN": "New token" + }, "JSON_EDIT": { "INVALID_JSON": "Niewłaściwy format JSON. Zmiany wprowadzone do zawartości formularza nie zostaną zapisane." }, -- GitLab From 8e0478f739bcc64885cc3c2e3a65d5e1288b3829 Mon Sep 17 00:00:00 2001 From: pgiertych <pgiertych@man.poznan.pl> Date: Wed, 10 Apr 2024 17:14:02 +0200 Subject: [PATCH 04/50] remove test controller --- .../portal/api/security/CustomAccessTokenController.java | 7 ------- .../portal/service/impl/CustomAccessTokenServiceImpl.java | 1 + 2 files changed, 1 insertion(+), 7 deletions(-) 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 index 1a7d19a72..647f129bf 100644 --- a/src/main/java/net/geant/nmaas/portal/api/security/CustomAccessTokenController.java +++ b/src/main/java/net/geant/nmaas/portal/api/security/CustomAccessTokenController.java @@ -43,13 +43,6 @@ public class CustomAccessTokenController { accessTokenService.invalidate(id); } - @GetMapping("/test") - public String testSecurity() { - return "works"; - } - - - private User getUser(Principal principal) { String principalName = principal.getName(); return userService.findByUsername(principalName) 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 index 90b0cf5ff..a2a6ff7bf 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/CustomAccessTokenServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/CustomAccessTokenServiceImpl.java @@ -43,6 +43,7 @@ public class CustomAccessTokenServiceImpl implements CustomAccessTokenService { } private String generateToken() { + // uuid is a placeholder for now return UUID.randomUUID().toString(); } -- GitLab From b4555d2a035a2fbaa9c16ab5a51919a04486cfa3 Mon Sep 17 00:00:00 2001 From: pgiertych <pgiertych@man.poznan.pl> Date: Wed, 10 Apr 2024 18:07:36 +0200 Subject: [PATCH 05/50] add name to access token --- .../security/CustomAccessTokenController.java | 5 +-- .../portal/persistent/entity/AccessToken.java | 2 ++ .../service/CustomAccessTokenService.java | 2 +- .../impl/CustomAccessTokenServiceImpl.java | 7 ++-- src/test/shell/data/i18n/de.json | 14 +++++++- src/test/shell/data/i18n/en.json | 14 +++++++- src/test/shell/data/i18n/fr.json | 34 +++++++++++++------ src/test/shell/data/i18n/pl.json | 14 +++++++- 8 files changed, 72 insertions(+), 20 deletions(-) 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 index 647f129bf..66839fd38 100644 --- a/src/main/java/net/geant/nmaas/portal/api/security/CustomAccessTokenController.java +++ b/src/main/java/net/geant/nmaas/portal/api/security/CustomAccessTokenController.java @@ -11,6 +11,7 @@ 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; @@ -33,9 +34,9 @@ public class CustomAccessTokenController { } @PostMapping() - public AccessToken createNewToken(Principal principal) { + public AccessToken createNewToken(Principal principal, @RequestBody String name) { User user = getUser(principal); - return accessTokenService.createToken(user.getId()); + return accessTokenService.createToken(user.getId(), name); } @PutMapping("/{id}") 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 index 2cf56de55..7d2f1932d 100644 --- a/src/main/java/net/geant/nmaas/portal/persistent/entity/AccessToken.java +++ b/src/main/java/net/geant/nmaas/portal/persistent/entity/AccessToken.java @@ -23,6 +23,8 @@ public class AccessToken { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + private String name; + private Long userId; private String tokenValue; diff --git a/src/main/java/net/geant/nmaas/portal/service/CustomAccessTokenService.java b/src/main/java/net/geant/nmaas/portal/service/CustomAccessTokenService.java index 5ba1a2268..96e59e1eb 100644 --- a/src/main/java/net/geant/nmaas/portal/service/CustomAccessTokenService.java +++ b/src/main/java/net/geant/nmaas/portal/service/CustomAccessTokenService.java @@ -7,7 +7,7 @@ import java.util.List; public interface CustomAccessTokenService { void invalidate(Long id); - AccessToken createToken(Long userId); + AccessToken createToken(Long userId, String name); List<AccessToken> getAll(Long userId); } 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 index a2a6ff7bf..58bea7e30 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/CustomAccessTokenServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/CustomAccessTokenServiceImpl.java @@ -24,8 +24,8 @@ public class CustomAccessTokenServiceImpl implements CustomAccessTokenService { } @Override - public AccessToken createToken(Long userId) { - AccessToken token = createNewToken(userId); + public AccessToken createToken(Long userId, String name) { + AccessToken token = createNewToken(userId, name); return accessTokenRepository.save(token); } @@ -34,8 +34,9 @@ public class CustomAccessTokenServiceImpl implements CustomAccessTokenService { return accessTokenRepository.findAllByUserId(userId); } - private AccessToken createNewToken(Long userId) { + private AccessToken createNewToken(Long userId, String name) { AccessToken token = new AccessToken(); + token.setName(name); token.setUserId(userId); token.setTokenValue(generateToken()); token.setValid(true); diff --git a/src/test/shell/data/i18n/de.json b/src/test/shell/data/i18n/de.json index 3239b4c99..e833a24cf 100644 --- a/src/test/shell/data/i18n/de.json +++ b/src/test/shell/data/i18n/de.json @@ -1155,13 +1155,25 @@ "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": "New token" + "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 8a1ce458e..c04aeb3f4 100644 --- a/src/test/shell/data/i18n/en.json +++ b/src/test/shell/data/i18n/en.json @@ -1157,13 +1157,25 @@ "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": "New token" + "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 7a1470747..fdc7764b4 100644 --- a/src/test/shell/data/i18n/fr.json +++ b/src/test/shell/data/i18n/fr.json @@ -1151,18 +1151,30 @@ } } }, - "TOKENS": { - "HEADER": "Tokens", - "TABLE": { - "ID": "ID", - "VALUE": "Value", - "VALID": "Valid", - "ACTIONS": "Actions" - }, - "BUTTON_INVALIDATE": "Invalidate", - "NO_TOKENS": "No tokens", - "NEW_TOKEN": "New token" + ""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 25f8a91e0..304c8ab41 100644 --- a/src/test/shell/data/i18n/pl.json +++ b/src/test/shell/data/i18n/pl.json @@ -1156,13 +1156,25 @@ "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": "New token" + "NEW_TOKEN": "Add new token" }, "JSON_EDIT": { "INVALID_JSON": "Niewłaściwy format JSON. Zmiany wprowadzone do zawartości formularza nie zostaną zapisane." -- GitLab From cb222262ed5f4122d5bb086e753163037f364aa6 Mon Sep 17 00:00:00 2001 From: pgiertych <pgiertych@man.poznan.pl> Date: Thu, 11 Apr 2024 10:32:42 +0200 Subject: [PATCH 06/50] fix translations --- src/test/shell/data/i18n/fr.json | 46 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/test/shell/data/i18n/fr.json b/src/test/shell/data/i18n/fr.json index fdc7764b4..5c11bc30c 100644 --- a/src/test/shell/data/i18n/fr.json +++ b/src/test/shell/data/i18n/fr.json @@ -1151,30 +1151,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" - } + "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" }, - "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." }, -- GitLab From eee0221b230251b65d157a95d2b6b5e15e2e7b19 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Wed, 4 Sep 2024 10:49:07 +0200 Subject: [PATCH 07/50] add state handler for APPLICATION_REMOVED --- .../orchestration/entities/AppDeploymentState.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) 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 c2e158254..b35e07d63 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 -- GitLab From 32cb15fa32424cc07488a26e6e5be44b0636b01c Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Wed, 4 Sep 2024 13:44:21 +0200 Subject: [PATCH 08/50] add refresh label --- src/test/shell/data/i18n/de.json | 3 ++- src/test/shell/data/i18n/en.json | 3 ++- src/test/shell/data/i18n/fr.json | 3 ++- src/test/shell/data/i18n/pl.json | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/test/shell/data/i18n/de.json b/src/test/shell/data/i18n/de.json index e3e42ed33..7c918b109 100644 --- a/src/test/shell/data/i18n/de.json +++ b/src/test/shell/data/i18n/de.json @@ -1212,7 +1212,8 @@ "DOMAIN" : "Domain", "CHECK_STATE" : "Check state", "UPLOAD_TEXT" : "or enter CSV content below", - "DOWNLOAD_CSV" : "Download CSV" + "DOWNLOAD_CSV" : "Download CSV", + "REFRESH" : "Refresh states" }, "STATE" : { "PENDING" : "Pending", diff --git a/src/test/shell/data/i18n/en.json b/src/test/shell/data/i18n/en.json index 402870080..b81160208 100644 --- a/src/test/shell/data/i18n/en.json +++ b/src/test/shell/data/i18n/en.json @@ -1215,7 +1215,8 @@ "DOMAIN" : "Domain", "CHECK_STATE" : "Check state", "UPLOAD_TEXT" : "or enter the csv content below", - "DOWNLOAD_CSV" : "Download CSV" + "DOWNLOAD_CSV" : "Download CSV", + "REFRESH" : "Refresh states" }, "STATE" : { "PENDING" : "Pending", diff --git a/src/test/shell/data/i18n/fr.json b/src/test/shell/data/i18n/fr.json index 48d78d0ed..6804efd13 100644 --- a/src/test/shell/data/i18n/fr.json +++ b/src/test/shell/data/i18n/fr.json @@ -1213,7 +1213,8 @@ "DOMAIN" : "Domain", "CHECK_STATE" : "Check state", "UPLOAD_TEXT" : "or enter CSV content below", - "DOWNLOAD_CSV" : "Download CSV" + "DOWNLOAD_CSV" : "Download CSV", + "REFRESH" : "Refresh states" }, "STATE" : { "PENDING" : "Pending", diff --git a/src/test/shell/data/i18n/pl.json b/src/test/shell/data/i18n/pl.json index d27810427..f96811b72 100644 --- a/src/test/shell/data/i18n/pl.json +++ b/src/test/shell/data/i18n/pl.json @@ -1214,7 +1214,8 @@ "DOMAIN" : "Domena", "CHECK_STATE" : "Sprawdź status", "UPLOAD_TEXT" : "lub podaj tekst w formacie CSV poniżej", - "DOWNLOAD_CSV" : "Pobierz CSV" + "DOWNLOAD_CSV" : "Pobierz CSV", + "REFRESH" : "Odśwież stany" }, "STATE" : { "PENDING" : "Oczekuje", -- GitLab From 0cda3fc8685bfb9ddf9d83f80c3305af43c94872 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Wed, 4 Sep 2024 13:44:34 +0200 Subject: [PATCH 09/50] Bulk update status command --- .../nmaas/portal/api/bulk/BulkController.java | 16 +++++- .../service/BulkApplicationService.java | 3 ++ .../impl/BulkApplicationServiceImpl.java | 53 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) 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 c42118894..a03794d9d 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 @@ -133,7 +133,7 @@ public class BulkController { User user = this.userService.findByUsername(principal.getName()).orElseThrow(() -> new MissingElementException("Missing user " + principal.getName())); return ResponseEntity.ok(mapToView(bulkDeploymentRepository.findByType(BulkType.DOMAIN)).stream() - .filter(bulk -> bulk.getCreator().getId().equals(user.getId())).collect(Collectors.toList())); + .filter(bulk -> bulk.getCreator().getId().equals(user.getId())).collect(Collectors.toList())); } @GetMapping("/apps") @@ -151,6 +151,12 @@ public class BulkController { .filter(bulk -> bulk.getCreator().getId().equals(user.getId())).collect(Collectors.toList())); } + @GetMapping("/refresh/{id}") + @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN') || hasRole('ROLE_VL_MANAGER')") + public ResponseEntity<BulkDeploymentViewS> getRefreshedState(@PathVariable Long id) { + return ResponseEntity.ok(mapToView(this.bulkApplicationService.updateState(id))); + } + private List<BulkDeploymentViewS> mapToView(List<BulkDeployment> deployments) { return deployments.stream() .map(bulk -> { @@ -162,6 +168,14 @@ public class BulkController { .collect(Collectors.toList()); } + private BulkDeploymentView mapToView(BulkDeployment deployment) { + BulkDeploymentView bulkView = modelMapper.map(deployment, BulkDeploymentView.class); + bulkView.setCreator(getUserView(deployment.getCreatorId())); + mapDetails(deployment, bulkView); + return bulkView; + + } + private void mapDetails(BulkDeployment deployment, BulkDeploymentViewS view) { if (deployment.getType().equals(BulkType.APPLICATION)) { Map<String, String> details = new HashMap<>(); 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 bebf1c9f8..08583400d 100644 --- a/src/main/java/net/geant/nmaas/portal/service/BulkApplicationService.java +++ b/src/main/java/net/geant/nmaas/portal/service/BulkApplicationService.java @@ -7,6 +7,7 @@ import net.geant.nmaas.portal.api.bulk.BulkDeploymentView; import net.geant.nmaas.portal.api.bulk.BulkDeploymentViewS; import net.geant.nmaas.portal.api.bulk.CsvApplication; import net.geant.nmaas.portal.api.domain.UserViewMinimal; +import net.geant.nmaas.portal.persistent.entity.BulkDeployment; import org.springframework.context.ApplicationEvent; import org.springframework.core.io.InputStreamResource; @@ -24,4 +25,6 @@ public interface BulkApplicationService { InputStreamResource getInputStreamAppBulkDetails(List<BulkAppDetails> list ); + BulkDeployment updateState(Long bulkId); + } 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 aea95a4ed..cb73a8fe9 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 @@ -55,6 +55,7 @@ import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -300,6 +301,58 @@ public class BulkApplicationServiceImpl implements BulkApplicationService { ); } + @Override + public BulkDeployment updateState(Long bulkId) { + log.info("Update all states for bulk {}", bulkId); + Optional<BulkDeployment> bulk = this.bulkDeploymentRepository.findById(bulkId); + if(bulk.isPresent()) { + BulkDeployment bulkDeployment = bulk.get(); + bulkDeployment.getEntries().forEach(entry -> { + try { + Long instanceId = Long.valueOf(entry.getDetails().get(BULK_ENTRY_DETAIL_KEY_APP_INSTANCE_ID)); + AppInstance instance = instanceService.find(instanceId).orElseThrow(); + + AppLifecycleState state = appDeploymentMonitor.state(instance.getInternalId()); + log.error("For bulk entries {} state = {}", entry.getId(), state.toString()); + switch (state) { + case APPLICATION_DEPLOYMENT_VERIFIED: + entry.setState(BulkDeploymentState.COMPLETED); + bulkDeploymentEntryRepository.save(entry); + break; + case APPLICATION_CONFIGURATION_FAILED: + case APPLICATION_DEPLOYMENT_FAILED: + case APPLICATION_DEPLOYMENT_VERIFICATION_FAILED: + case INTERNAL_ERROR: + entry.setState(BulkDeploymentState.FAILED); + bulkDeploymentEntryRepository.save(entry); + break; + default: + entry.setState(BulkDeploymentState.PENDING); + bulkDeploymentEntryRepository.save(entry); + break; + } + logBulkStateUpdate(entry.getId(), entry.getState().name()); + + } catch (Exception e) { + log.error("Can not update state of {} bulk entry", entry.getId()); + } + }); + if (bulkDeployment.getEntries().stream().allMatch(e -> BulkDeploymentState.COMPLETED.equals(e.getState()))) { + bulkDeployment.setState(BulkDeploymentState.COMPLETED); + } else if (bulkDeployment.getEntries().stream().allMatch(e -> BulkDeploymentState.FAILED.equals(e.getState()))) { + bulkDeployment.setState(BulkDeploymentState.FAILED); + } else if (bulkDeployment.getEntries().stream().anyMatch(e -> BulkDeploymentState.FAILED.equals(e.getState()))) { + bulkDeployment.setState(BulkDeploymentState.PARTIALLY_FAILED); + } + logBulkStateUpdate(bulkDeployment.getId(),bulkDeployment.getState().name()); + bulkDeploymentRepository.save(bulkDeployment); + return bulkDeployment; + } else { + log.error("Can not find bulk deployment {}", bulkId); + throw new MissingElementException("Can not find bulk deployment " + bulkId); + } + } + private static BulkDeployment createBulkDeployment(UserViewMinimal creator) { BulkDeployment bulkDeployment = new BulkDeployment(); bulkDeployment.setType(BulkType.APPLICATION); -- GitLab From d686d1f2744cc8f80063f0cb836aa6fcf208ffab Mon Sep 17 00:00:00 2001 From: llopat <llopat@man.poznan.pl> Date: Fri, 6 Sep 2024 13:54:07 +0200 Subject: [PATCH 10/50] Update version to 1.7.0-SNAPSHOT --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 94458330e..3a0d07daa 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ repositories { mavenCentral() } -version = '1.6.3' +version = '1.7.0-SNAPSHOT' group = 'net.geant.nmaas' java { -- GitLab From 404616eafeeeaa3bfec378951e93599f59a1db5c Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:30:56 +0200 Subject: [PATCH 11/50] Bulk delete update --- .../geant/nmaas/portal/api/bulk/BulkController.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) 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 df2fd49cc..ea7f46dd5 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 @@ -14,6 +14,7 @@ import net.geant.nmaas.portal.service.BulkDomainService; import net.geant.nmaas.portal.service.UserService; import org.modelmapper.ModelMapper; import org.springframework.core.io.InputStreamResource; +import org.springframework.dao.PermissionDeniedDataAccessException; import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -151,16 +152,22 @@ public class BulkController { } @DeleteMapping("/{id}") - @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN')") + @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN') || hasRole('ROLE_VL_MANAGER')") public ResponseEntity<Void> removeBulkDeployment( @PathVariable Long id, - @RequestParam(name = "removeAll") boolean removeApps + @RequestParam(name = "removeAll") boolean removeApps, + Principal principal ) { + User user = this.userService.findByUsername(principal.getName()).orElseThrow(() -> new MissingElementException("Missing user " + principal.getName())); Optional<BulkDeployment> bulk = this.bulkDeploymentRepository.findById(id); if (bulk.isEmpty()) { return ResponseEntity.notFound().build(); } + + if(bulk.get().getCreatorId().equals(user.getId()) ) { + throw new PermissionDeniedDataAccessException("User doesnt have access to this bulk deployment", new Throwable()); + } if (removeApps) { bulkApplicationService.deleteAppInstancesFromBulk(mapToView(bulk.get(), BulkDeploymentView.class)); } -- GitLab From d6830306abf17a5d260396c92427a7e9ef27f1b2 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:20:38 +0200 Subject: [PATCH 12/50] update merge --- .../java/net/geant/nmaas/portal/api/bulk/BulkController.java | 5 +++++ 1 file changed, 5 insertions(+) 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 b92cedea4..0ae731c41 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 @@ -176,6 +176,11 @@ public class BulkController { } private List<BulkDeploymentViewS> mapToViewList(List<BulkDeployment> deployments) { + return deployments.stream() + .map(bulk -> mapToView(bulk, BulkDeploymentViewS.class)) + .collect(Collectors.toList()); + } + @GetMapping("/refresh/{id}") @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN') || hasRole('ROLE_VL_MANAGER')") public ResponseEntity<BulkDeploymentViewS> getRefreshedState(@PathVariable Long id) { -- GitLab From 5816101ec682548735a878cdb8d9cfc14b4dbe3c Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:33:38 +0200 Subject: [PATCH 13/50] Add flyway for accessToken --- .../geant/nmaas/portal/persistent/entity/AccessToken.java | 2 +- src/main/resources/application.properties | 4 ++-- .../common/V1.7.0_20240920_1430__addedAccessTokens.sql | 8 ++++++++ 3 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 src/main/resources/db/migration/common/V1.7.0_20240920_1430__addedAccessTokens.sql 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 index 7d2f1932d..80c117b2a 100644 --- a/src/main/java/net/geant/nmaas/portal/persistent/entity/AccessToken.java +++ b/src/main/java/net/geant/nmaas/portal/persistent/entity/AccessToken.java @@ -12,7 +12,7 @@ import javax.persistence.Id; import javax.persistence.Table; @Entity -@Table(name = "accessTokens") +@Table(name = "access_tokens") @NoArgsConstructor @Getter @Setter diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index de4403d1a..61b016016 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -60,8 +60,8 @@ db.standalone.username=nmaas db.standalone.password=nmaas # Common spring.h2.console.enabled=true -spring.jpa.properties.hibernate.show_sql=false -spring.jpa.properties.hibernate.format_sql=false +spring.jpa.properties.hibernate.show_sql=true +spring.jpa.properties.hibernate.format_sql=true spring.jpa.properties.hibernate.connection.autocommit=false spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.show-sql=true 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 000000000..cf5778322 --- /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 -- GitLab From bfd52b2f1e07536149ff84de0451aa4cc384d6de Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:33:50 +0200 Subject: [PATCH 14/50] Add flyway for accessToken --- .../common/V1.7.0_20240920_1430__addedAccessTokens.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index cf5778322..d81247f35 100644 --- 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 @@ -5,4 +5,4 @@ create table access_tokens ( user_id bigint, valid boolean not null, primary key (id) - ) \ No newline at end of file + ó); \ No newline at end of file -- GitLab From a5306cc1cf3721368ac55e4f2ceca9d0a00f18f3 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:33:58 +0200 Subject: [PATCH 15/50] Add flyway for accessToken --- .../common/V1.7.0_20240920_1430__addedAccessTokens.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index d81247f35..999454960 100644 --- 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 @@ -5,4 +5,4 @@ create table access_tokens ( user_id bigint, valid boolean not null, primary key (id) - ó); \ No newline at end of file + ); \ No newline at end of file -- GitLab From 21b1e4b3ba90a0b3a78ef363b560f6956648d943 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Fri, 20 Sep 2024 16:01:09 +0200 Subject: [PATCH 16/50] reverse sql --- src/main/resources/application.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 61b016016..de4403d1a 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -60,8 +60,8 @@ db.standalone.username=nmaas db.standalone.password=nmaas # Common spring.h2.console.enabled=true -spring.jpa.properties.hibernate.show_sql=true -spring.jpa.properties.hibernate.format_sql=true +spring.jpa.properties.hibernate.show_sql=false +spring.jpa.properties.hibernate.format_sql=false spring.jpa.properties.hibernate.connection.autocommit=false spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.show-sql=true -- GitLab From f1ffc4392507d4ce1bb972e7bcff3da0d7d9eb3f Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Fri, 20 Sep 2024 16:02:55 +0200 Subject: [PATCH 17/50] delete log --- .../nmaas/portal/service/impl/BulkApplicationServiceImpl.java | 1 - 1 file changed, 1 deletion(-) 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 9f6544972..c7e5ae6c4 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 @@ -333,7 +333,6 @@ public class BulkApplicationServiceImpl implements BulkApplicationService { AppInstance instance = instanceService.find(instanceId).orElseThrow(); AppLifecycleState state = appDeploymentMonitor.state(instance.getInternalId()); - log.error("For bulk entries {} state = {}", entry.getId(), state.toString()); switch (state) { case APPLICATION_DEPLOYMENT_VERIFIED: entry.setState(BulkDeploymentState.COMPLETED); -- GitLab From 8e50b2bd42497f747ed25b37000bd2d8d552bee4 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Tue, 24 Sep 2024 11:19:12 +0200 Subject: [PATCH 18/50] testing handler --- .../exceptions/IllegalExceptionHandler.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/main/java/net/geant/nmaas/portal/exceptions/IllegalExceptionHandler.java diff --git a/src/main/java/net/geant/nmaas/portal/exceptions/IllegalExceptionHandler.java b/src/main/java/net/geant/nmaas/portal/exceptions/IllegalExceptionHandler.java new file mode 100644 index 000000000..5c83a2679 --- /dev/null +++ b/src/main/java/net/geant/nmaas/portal/exceptions/IllegalExceptionHandler.java @@ -0,0 +1,20 @@ +package net.geant.nmaas.portal.exceptions; + +import net.bytebuddy.pool.TypePool; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class IllegalExceptionHandler { + + @ExceptionHandler(IllegalArgumentException.class) + public ResponseEntity<?> handle(IllegalArgumentException ex) { + throw new ObjectAlreadyExistsException(ex.getMessage()); + } + + @ExceptionHandler(IllegalStateException.class) + public ResponseEntity<?> handle(IllegalStateException ex) { + throw new ObjectAlreadyExistsException(ex.getMessage()); + } +} -- GitLab From 8b5451c0f229e150e1f84a522ba570c4895db041 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Tue, 24 Sep 2024 12:20:15 +0200 Subject: [PATCH 19/50] delete appbase from appstateperdomain --- .../geant/nmaas/portal/persistent/entity/DomainGroup.java | 1 + .../net/geant/nmaas/portal/service/DomainGroupService.java | 3 +++ .../service/impl/ApplicationStatePerDomainServiceImpl.java | 1 - .../nmaas/portal/service/impl/DomainGroupServiceImpl.java | 7 +++++++ .../geant/nmaas/portal/service/impl/DomainServiceImpl.java | 2 +- 5 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/geant/nmaas/portal/persistent/entity/DomainGroup.java b/src/main/java/net/geant/nmaas/portal/persistent/entity/DomainGroup.java index 36f735f09..1533eaea4 100644 --- a/src/main/java/net/geant/nmaas/portal/persistent/entity/DomainGroup.java +++ b/src/main/java/net/geant/nmaas/portal/persistent/entity/DomainGroup.java @@ -23,6 +23,7 @@ import javax.validation.constraints.NotNull; import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; @Entity diff --git a/src/main/java/net/geant/nmaas/portal/service/DomainGroupService.java b/src/main/java/net/geant/nmaas/portal/service/DomainGroupService.java index f8609b69c..a95e5c3c1 100644 --- a/src/main/java/net/geant/nmaas/portal/service/DomainGroupService.java +++ b/src/main/java/net/geant/nmaas/portal/service/DomainGroupService.java @@ -1,6 +1,7 @@ package net.geant.nmaas.portal.service; import net.geant.nmaas.portal.api.domain.DomainGroupView; +import net.geant.nmaas.portal.persistent.entity.ApplicationBase; import net.geant.nmaas.portal.persistent.entity.Domain; import java.util.List; @@ -23,4 +24,6 @@ public interface DomainGroupService { DomainGroupView updateDomainGroup(Long domainGroupId, DomainGroupView view); + void deleteAppBaseFromAllAppState(ApplicationBase base); + } diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationStatePerDomainServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationStatePerDomainServiceImpl.java index cd043eb0f..297af2ebc 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationStatePerDomainServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationStatePerDomainServiceImpl.java @@ -101,5 +101,4 @@ public class ApplicationStatePerDomainServiceImpl implements ApplicationStatePer public boolean validateAppConfigurationAgainstState(AppConfigurationView appConfig, ApplicationStatePerDomain appState) { return appConfig.getStorageSpace() == null || appConfig.getStorageSpace() <= appState.getPvStorageSizeLimit(); } - } diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/DomainGroupServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/DomainGroupServiceImpl.java index 0c4cd891b..32c7e7598 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/DomainGroupServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/DomainGroupServiceImpl.java @@ -6,6 +6,7 @@ import net.geant.nmaas.portal.api.domain.ApplicationStatePerDomainView; import net.geant.nmaas.portal.api.domain.DomainGroupView; import net.geant.nmaas.portal.api.exception.MissingElementException; import net.geant.nmaas.portal.api.exception.ProcessingException; +import net.geant.nmaas.portal.persistent.entity.ApplicationBase; import net.geant.nmaas.portal.persistent.entity.ApplicationStatePerDomain; import net.geant.nmaas.portal.persistent.entity.Domain; import net.geant.nmaas.portal.persistent.entity.DomainGroup; @@ -136,4 +137,10 @@ public class DomainGroupServiceImpl implements DomainGroupService { } } + public void deleteAppBaseFromAllAppState(ApplicationBase base) { + domainGroupRepository.findAll().forEach(d -> { + d.getApplicationStatePerDomain().removeIf(state -> state.getApplicationBase().equals(base)); + }); + } + } \ No newline at end of file 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 7f4ff1aff..0caa03568 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 @@ -536,8 +536,8 @@ public class DomainServiceImpl implements DomainService { public void removeAppBaseFromAllDomains(ApplicationBase base) { getDomains().forEach(domain -> { removeFromDomain(base, domain); - }); + domainGroupService.deleteAppBaseFromAllAppState(base); } private void removeFromDomain(ApplicationBase base, Domain domain) { -- GitLab From 98d6384e1c4373247dd884e9f8bcac1d4e166bd4 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Tue, 24 Sep 2024 12:41:07 +0200 Subject: [PATCH 20/50] delete appbase from appstateperdomain --- .../portal/service/impl/DomainServiceTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) 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 d3c645f89..e9e2e9922 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 @@ -473,4 +473,22 @@ public class DomainServiceTest { assertEquals(0, domain2.getApplicationStatePerDomain().size()); } + @Test + void shouldRemoveAppBaseFromAllDomainGroup() { + ApplicationBase applicationBase = new ApplicationBase(1L, "appBase"); + ApplicationStatePerDomain statePerDomain = new ApplicationStatePerDomain(applicationBase); + DomainGroup domainGroup = new DomainGroup("test", "test1"); + DomainGroup domainGroup2 = new DomainGroup("test2", "test2"); + domainGroup.setApplicationStatePerDomain(new ArrayList<>(List.of(statePerDomain))); + domainGroup2.setApplicationStatePerDomain(new ArrayList<>(List.of(statePerDomain))); + when(domainGroupRepository.findAll()).thenReturn(List.of(domainGroup, domainGroup2)); + + domainGroupService.deleteAppBaseFromAllAppState(applicationBase); + + assertEquals(0, domainGroup.getApplicationStatePerDomain().size()); + assertEquals(0, domainGroup2.getApplicationStatePerDomain().size()); + + + } + } -- GitLab From ce39ad083b637f48622904fbc5053bbf4450fde3 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Thu, 26 Sep 2024 11:31:20 +0200 Subject: [PATCH 21/50] update domains group app adding --- .../service/impl/ApplicationStatePerDomainServiceImpl.java | 7 +++++++ .../impl/ApplicationStatePerDomainServiceImplTest.java | 5 ++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationStatePerDomainServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationStatePerDomainServiceImpl.java index 297af2ebc..c11f3b1d6 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationStatePerDomainServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationStatePerDomainServiceImpl.java @@ -9,6 +9,7 @@ import net.geant.nmaas.portal.persistent.entity.ApplicationBase; import net.geant.nmaas.portal.persistent.entity.ApplicationStatePerDomain; import net.geant.nmaas.portal.persistent.entity.Domain; import net.geant.nmaas.portal.persistent.repositories.ApplicationBaseRepository; +import net.geant.nmaas.portal.persistent.repositories.DomainGroupRepository; import net.geant.nmaas.portal.persistent.repositories.DomainRepository; import net.geant.nmaas.portal.service.ApplicationStatePerDomainService; import org.springframework.stereotype.Service; @@ -25,6 +26,7 @@ public class ApplicationStatePerDomainServiceImpl implements ApplicationStatePer private final DomainRepository domainRepository; private final ApplicationBaseRepository applicationBaseRepository; + private final DomainGroupRepository domainGroupRepository; @Override public List<ApplicationStatePerDomain> generateListOfDefaultApplicationStatesPerDomain() { @@ -44,6 +46,11 @@ public class ApplicationStatePerDomainServiceImpl implements ApplicationStatePer appState.setPvStorageSizeLimit(ApplicationStatePerDomainServiceImpl.DEFAULT_PV_STORAGE_SIZE_LIMIT); List<Domain> allDomains = domainRepository.findAll(); allDomains.forEach(domain -> domain.addApplicationState(appState)); + //update domains groups - set app to false by default + appState.setEnabled(false); + domainGroupRepository.findAll().forEach(d -> { + d.getApplicationStatePerDomain().add(appState); + }); return domainRepository.saveAll(allDomains); } diff --git a/src/test/java/net/geant/nmaas/portal/service/impl/ApplicationStatePerDomainServiceImplTest.java b/src/test/java/net/geant/nmaas/portal/service/impl/ApplicationStatePerDomainServiceImplTest.java index 2203f1e38..0bfe44f77 100644 --- a/src/test/java/net/geant/nmaas/portal/service/impl/ApplicationStatePerDomainServiceImplTest.java +++ b/src/test/java/net/geant/nmaas/portal/service/impl/ApplicationStatePerDomainServiceImplTest.java @@ -5,6 +5,7 @@ import net.geant.nmaas.portal.persistent.entity.ApplicationBase; import net.geant.nmaas.portal.persistent.entity.ApplicationStatePerDomain; import net.geant.nmaas.portal.persistent.entity.Domain; import net.geant.nmaas.portal.persistent.repositories.ApplicationBaseRepository; +import net.geant.nmaas.portal.persistent.repositories.DomainGroupRepository; import net.geant.nmaas.portal.persistent.repositories.DomainRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -28,6 +29,8 @@ public class ApplicationStatePerDomainServiceImplTest { private final DomainRepository domains = mock(DomainRepository.class); private final ApplicationBaseRepository applications = mock(ApplicationBaseRepository.class); + private final DomainGroupRepository domainGroupRepository = mock(DomainGroupRepository.class); + private ApplicationStatePerDomainServiceImpl appState; private final Domain domain1 = mock(Domain.class); @@ -35,7 +38,7 @@ public class ApplicationStatePerDomainServiceImplTest { @BeforeEach void setup() { - appState = new ApplicationStatePerDomainServiceImpl(domains, applications); + appState = new ApplicationStatePerDomainServiceImpl(domains, applications, domainGroupRepository); } @Test -- GitLab From 3cfc22afa3915af95f494e01ff2323de83c64ef0 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:14:08 +0200 Subject: [PATCH 22/50] update handler --- .../exceptions/IllegalExceptionHandler.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/geant/nmaas/portal/exceptions/IllegalExceptionHandler.java b/src/main/java/net/geant/nmaas/portal/exceptions/IllegalExceptionHandler.java index 5c83a2679..983d4b3b9 100644 --- a/src/main/java/net/geant/nmaas/portal/exceptions/IllegalExceptionHandler.java +++ b/src/main/java/net/geant/nmaas/portal/exceptions/IllegalExceptionHandler.java @@ -1,20 +1,31 @@ package net.geant.nmaas.portal.exceptions; +import lombok.extern.slf4j.Slf4j; import net.bytebuddy.pool.TypePool; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; @ControllerAdvice +@Slf4j public class IllegalExceptionHandler { @ExceptionHandler(IllegalArgumentException.class) public ResponseEntity<?> handle(IllegalArgumentException ex) { - throw new ObjectAlreadyExistsException(ex.getMessage()); + log.error("Test throw ? "); + return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_ACCEPTABLE); } @ExceptionHandler(IllegalStateException.class) public ResponseEntity<?> handle(IllegalStateException ex) { - throw new ObjectAlreadyExistsException(ex.getMessage()); + log.error("Test throw 2 ? "); + return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_ACCEPTABLE); + } + + @ExceptionHandler(RuntimeException.class) + public ResponseEntity<?> handle(RuntimeException ex) { + log.error("Test throw 3 ? "); + return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_ACCEPTABLE); } } -- GitLab From 70c947dd4cc5c82f63441efed95005f496f7ba2d Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Thu, 26 Sep 2024 14:12:15 +0200 Subject: [PATCH 23/50] add caching option for main page request --- build.gradle | 3 +++ src/main/java/net/geant/nmaas/MainConfig.java | 2 ++ .../persistent/repositories/ApplicationBaseRepository.java | 5 +++++ .../portal/service/impl/ApplicationBaseServiceImpl.java | 5 ++--- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 3a0d07daa..bc971ee4c 100644 --- a/build.gradle +++ b/build.gradle @@ -95,6 +95,8 @@ dependencies { implementation('org.springframework.boot:spring-boot-starter-quartz') implementation('org.springframework.boot:spring-boot-starter-log4j2') implementation('org.springframework.boot:spring-boot-starter-validation') + implementation 'org.springframework.boot:spring-boot-starter-cache' + implementation('org.springdoc:springdoc-openapi-ui:1.6.15') @@ -114,6 +116,7 @@ dependencies { implementation('com.vdurmont:semver4j:3.1.0') implementation('io.micrometer:micrometer-registry-prometheus:1.11.2') + // SSH library implementation('com.hierynomus:sshj:0.32.0') diff --git a/src/main/java/net/geant/nmaas/MainConfig.java b/src/main/java/net/geant/nmaas/MainConfig.java index 925bf1973..dfdb09578 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/portal/persistent/repositories/ApplicationBaseRepository.java b/src/main/java/net/geant/nmaas/portal/persistent/repositories/ApplicationBaseRepository.java index f5398bb34..52ea84b06 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; @@ -27,6 +28,10 @@ public interface ApplicationBaseRepository extends JpaRepository<ApplicationBase @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) List<ApplicationBaseS> findAllSmall(); + @Cacheable("applicationBaseS") + @Query("SELECT ab FROM ApplicationBase ab JOIN Application a on a.name = ab.name WHERE a.state = 'ACTIVE'") + List<ApplicationBaseS> findAllSmall2(); + @Query("SELECT ab.tags FROM ApplicationBase ab WHERE ab.id =?1") List<Tag> findAllBaseTag(Long baseId); 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 d752b8963..82743ac7c 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 @@ -136,13 +136,12 @@ public class ApplicationBaseServiceImpl implements ApplicationBaseService { public List<ApplicationBaseViewS> findAllActiveAppsSmall() { log.debug("Loading information about all applications"); LocalDateTime beginning = LocalDateTime.now(); - List<ApplicationBaseS> allSmall = appBaseRepository.findAllSmall(); + List<ApplicationBaseS> allSmall = appBaseRepository.findAllSmall2(); LocalDateTime end = LocalDateTime.now(); 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()); -- GitLab From 7e01d857847adece8834178b33b26b3e7fa05bd3 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Thu, 26 Sep 2024 14:13:26 +0200 Subject: [PATCH 24/50] change query names --- .../persistent/repositories/ApplicationBaseRepository.java | 5 +---- .../portal/service/impl/ApplicationBaseServiceImpl.java | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) 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 52ea84b06..77ef01da5 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 @@ -25,12 +25,9 @@ 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) - List<ApplicationBaseS> findAllSmall(); - @Cacheable("applicationBaseS") @Query("SELECT ab FROM ApplicationBase ab JOIN Application a on a.name = ab.name WHERE a.state = 'ACTIVE'") - List<ApplicationBaseS> findAllSmall2(); + List<ApplicationBaseS> findAllSmall(); @Query("SELECT ab.tags FROM ApplicationBase ab WHERE ab.id =?1") List<Tag> findAllBaseTag(Long baseId); 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 82743ac7c..d2b26b5b9 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 @@ -136,12 +136,11 @@ public class ApplicationBaseServiceImpl implements ApplicationBaseService { public List<ApplicationBaseViewS> findAllActiveAppsSmall() { log.debug("Loading information about all applications"); LocalDateTime beginning = LocalDateTime.now(); - List<ApplicationBaseS> allSmall = appBaseRepository.findAllSmall2(); + List<ApplicationBaseS> allSmall = appBaseRepository.findAllSmall(); LocalDateTime end = LocalDateTime.now(); 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)) - .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()); -- GitLab From ba554c38ebd111254af87fed06c2e2aea9425f9d Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Fri, 27 Sep 2024 11:26:56 +0200 Subject: [PATCH 25/50] update query and test --- .../api/configuration/TestCacheConfig.java | 15 +++++++++++++ .../market/ApplicationControllerIntTest.java | 22 +++++++++++-------- .../resources/application.properties | 2 ++ .../ApplicationBaseRepository.java | 2 +- .../impl/ApplicationBaseServiceImpl.java | 7 ++++++ .../service/impl/ApplicationServiceImpl.java | 6 +++++ 6 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 src/integrationTest/java/net/geant/nmaas/portal/api/configuration/TestCacheConfig.java 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 000000000..fd4038056 --- /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 f2f9b6b7f..2610b3835 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/resources/application.properties b/src/integrationTest/resources/application.properties index 5164bcec6..f4df103d0 100644 --- a/src/integrationTest/resources/application.properties +++ b/src/integrationTest/resources/application.properties @@ -159,3 +159,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/portal/persistent/repositories/ApplicationBaseRepository.java b/src/main/java/net/geant/nmaas/portal/persistent/repositories/ApplicationBaseRepository.java index 77ef01da5..b4b89368b 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 @@ -26,7 +26,7 @@ public interface ApplicationBaseRepository extends JpaRepository<ApplicationBase long countAllActive(); @Cacheable("applicationBaseS") - @Query("SELECT ab FROM ApplicationBase ab JOIN Application a on a.name = ab.name WHERE a.state = 'ACTIVE'") + @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/impl/ApplicationBaseServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/ApplicationBaseServiceImpl.java index d2b26b5b9..c0b95f5da 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() @@ -170,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 789cdb3d2..0751c87a6 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."); -- GitLab From fe7084d7791352e7c2bf4dbb10a3505e65ea57f2 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:41:23 +0200 Subject: [PATCH 26/50] Add helmrepoupdate on ApplicationListUpdateEvent --- .../kubernetes/HelmRepoUpdateListener.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/HelmRepoUpdateListener.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/HelmRepoUpdateListener.java index c827d8f5c..d3f980e13 100644 --- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/HelmRepoUpdateListener.java +++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/HelmRepoUpdateListener.java @@ -3,6 +3,7 @@ package net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes; import lombok.RequiredArgsConstructor; import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.components.helm.HelmKServiceManager; import net.geant.nmaas.portal.events.ApplicationActivatedEvent; +import net.geant.nmaas.portal.events.ApplicationListUpdatedEvent; import net.geant.nmaas.utils.logging.LogLevel; import net.geant.nmaas.utils.logging.Loggable; import org.springframework.context.ApplicationEvent; @@ -22,4 +23,11 @@ public class HelmRepoUpdateListener { return null; } + @EventListener + @Loggable(LogLevel.INFO) + public ApplicationEvent trigger(ApplicationListUpdatedEvent event) { + helmKServiceManager.updateHelmRepo(); + return null; + } + } -- GitLab From 1e241c04dd6917dd16e4b93144bc790dab07252c Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:57:10 +0200 Subject: [PATCH 27/50] Add helmrepoupdate on ApplicationListUpdateEvent --- .../kubernetes/HelmRepoUpdateListener.java | 7 ------- .../components/helm/HelmChartUpdateListener.java | 1 + 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/HelmRepoUpdateListener.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/HelmRepoUpdateListener.java index d3f980e13..734014f1e 100644 --- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/HelmRepoUpdateListener.java +++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/HelmRepoUpdateListener.java @@ -23,11 +23,4 @@ public class HelmRepoUpdateListener { return null; } - @EventListener - @Loggable(LogLevel.INFO) - public ApplicationEvent trigger(ApplicationListUpdatedEvent event) { - helmKServiceManager.updateHelmRepo(); - return null; - } - } diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmChartUpdateListener.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmChartUpdateListener.java index e5fc014ca..0e2825320 100644 --- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmChartUpdateListener.java +++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/components/helm/HelmChartUpdateListener.java @@ -35,6 +35,7 @@ public class HelmChartUpdateListener { helmCommandExecutor.executeHelmRepoAddCommand(repoName, repoUrl); } } + helmCommandExecutor.executeHelmRepoUpdateCommand(); return null; } -- GitLab From 259575eb49f0a66fb8ad3053d07ec6bfbded84f9 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Tue, 1 Oct 2024 11:28:34 +0200 Subject: [PATCH 28/50] delete import --- .../kubernetes/HelmRepoUpdateListener.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/HelmRepoUpdateListener.java b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/HelmRepoUpdateListener.java index 734014f1e..c827d8f5c 100644 --- a/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/HelmRepoUpdateListener.java +++ b/src/main/java/net/geant/nmaas/nmservice/deployment/containerorchestrators/kubernetes/HelmRepoUpdateListener.java @@ -3,7 +3,6 @@ package net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes; import lombok.RequiredArgsConstructor; import net.geant.nmaas.nmservice.deployment.containerorchestrators.kubernetes.components.helm.HelmKServiceManager; import net.geant.nmaas.portal.events.ApplicationActivatedEvent; -import net.geant.nmaas.portal.events.ApplicationListUpdatedEvent; import net.geant.nmaas.utils.logging.LogLevel; import net.geant.nmaas.utils.logging.Loggable; import org.springframework.context.ApplicationEvent; -- GitLab From dfa238fd826c46820b8004c02562e5a40264ed80 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Thu, 3 Oct 2024 09:32:52 +0200 Subject: [PATCH 29/50] Update translation --- src/test/shell/data/i18n/de.json | 7 ++++--- src/test/shell/data/i18n/en.json | 7 ++++--- src/test/shell/data/i18n/fr.json | 7 ++++--- src/test/shell/data/i18n/pl.json | 5 +++-- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/test/shell/data/i18n/de.json b/src/test/shell/data/i18n/de.json index 0f09b429b..a3df58252 100644 --- a/src/test/shell/data/i18n/de.json +++ b/src/test/shell/data/i18n/de.json @@ -285,9 +285,10 @@ }, "SORT_MODE": { "NONE": "None", - "NAME": "By name", - "RATING": "Top rated", - "POPULAR": "Most popular" + "NAME": "Name", + "RATING": "Rating", + "POPULAR": "Popularity", + "DATE" : "Date added" } }, "MONITOR": { diff --git a/src/test/shell/data/i18n/en.json b/src/test/shell/data/i18n/en.json index 8483d4366..e4b40cf3a 100644 --- a/src/test/shell/data/i18n/en.json +++ b/src/test/shell/data/i18n/en.json @@ -285,9 +285,10 @@ }, "SORT_MODE": { "NONE": "None", - "NAME": "By name", - "RATING": "Top rated", - "POPULAR": "Most popular" + "NAME": "Name", + "RATING": "Rating", + "POPULAR": "Popularity", + "DATE" : "Date added" } }, "MONITOR": { diff --git a/src/test/shell/data/i18n/fr.json b/src/test/shell/data/i18n/fr.json index 44607c6f5..24affb2c2 100644 --- a/src/test/shell/data/i18n/fr.json +++ b/src/test/shell/data/i18n/fr.json @@ -285,9 +285,10 @@ }, "SORT_MODE": { "NONE": "None", - "NAME": "By name", - "RATING": "Top rated", - "POPULAR": "Most popular" + "NAME": "Name", + "RATING": "Rating", + "POPULAR": "Popularity", + "DATE" : "Date added" } }, "MONITOR": { diff --git a/src/test/shell/data/i18n/pl.json b/src/test/shell/data/i18n/pl.json index 66b386afb..151d81c3e 100644 --- a/src/test/shell/data/i18n/pl.json +++ b/src/test/shell/data/i18n/pl.json @@ -286,8 +286,9 @@ "SORT_MODE": { "NONE": "Brak", "NAME": "Nazwa", - "RATING": "Najlepiej oceniane", - "POPULAR": "Najbardziej popularne" + "RATING": "Ocena", + "POPULAR": "Popularność", + "DATE" : "Data dodania" } }, "MONITOR": { -- GitLab From ecdb42c68b25cfd040f02342a72e3ffab94feece Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:37:03 +0200 Subject: [PATCH 30/50] New SSOuser set firstname and lastname --- .../net/geant/nmaas/portal/service/impl/UserServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/UserServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/UserServiceImpl.java index ff1163577..a4b8e58a3 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/UserServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/UserServiceImpl.java @@ -188,6 +188,8 @@ public class UserServiceImpl implements UserService { if (configurationManager.getConfiguration().isBulkDomainsAllowForSsoAccounts()) { if (csvUser.getSsoEnabled() != null && csvUser.getSsoEnabled()) { newUser.setSamlToken(csvUser.getEmail()); + newUser.setFirstname(csvUser.getAdminUserName()); + newUser.setLastname(csvUser.getAdminUserName()); if(sendMails) this.sendMail(newUser, MailType.NEW_BULK_SSO_LOGIN); }else { if(sendMails) this.sendMail(newUser, MailType.NEW_BULK_LOGIN); -- GitLab From a6c1056eb051826a3cd66d0685de3206beafbe67 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:37:17 +0200 Subject: [PATCH 31/50] add try catch for setting the creator --- .../geant/nmaas/portal/api/bulk/BulkController.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) 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 0ae731c41..2b2113fcf 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 @@ -195,14 +195,22 @@ public class BulkController { private <T extends BulkDeploymentViewS> T mapToView(BulkDeployment bulk, Class<T> viewType) { T bulkView = modelMapper.map(bulk, viewType); - bulkView.setCreator(getUserView(bulk.getCreatorId())); + try { + bulkView.setCreator(getUserView(bulk.getCreatorId())); + } catch (Exception ex) { + log.error("Can not find creator for {} - creatorId: {}", bulk.getId(), bulk.getCreatorId()); + } mapDetails(bulk, bulkView); return bulkView; } private BulkDeploymentView mapToView(BulkDeployment deployment) { BulkDeploymentView bulkView = modelMapper.map(deployment, BulkDeploymentView.class); - bulkView.setCreator(getUserView(deployment.getCreatorId())); + try { + bulkView.setCreator(getUserView(deployment.getCreatorId())); + } catch (Exception ex) { + log.error("Can not find creator for {} - creatorId: {}", deployment.getId(), deployment.getCreatorId()); + } mapDetails(deployment, bulkView); return bulkView; -- GitLab From fd0d9273dad79d0a6f7949b2d0cd628c0aff9303 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:44:04 +0200 Subject: [PATCH 32/50] add try catch for setting the creator --- .../java/net/geant/nmaas/portal/api/bulk/BulkController.java | 2 ++ 1 file changed, 2 insertions(+) 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 2b2113fcf..dc3629c55 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 @@ -199,6 +199,7 @@ public class BulkController { bulkView.setCreator(getUserView(bulk.getCreatorId())); } catch (Exception ex) { log.error("Can not find creator for {} - creatorId: {}", bulk.getId(), bulk.getCreatorId()); + return null; } mapDetails(bulk, bulkView); return bulkView; @@ -208,6 +209,7 @@ public class BulkController { BulkDeploymentView bulkView = modelMapper.map(deployment, BulkDeploymentView.class); try { bulkView.setCreator(getUserView(deployment.getCreatorId())); + return null; } catch (Exception ex) { log.error("Can not find creator for {} - creatorId: {}", deployment.getId(), deployment.getCreatorId()); } -- GitLab From e6529122a34d736bd4322277c2329ab7fa7b1bdc Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Tue, 8 Oct 2024 12:35:47 +0200 Subject: [PATCH 33/50] add user manager delete before user database delete --- .../net/geant/nmaas/portal/service/DomainGroupService.java | 2 ++ .../nmaas/portal/service/impl/DomainGroupServiceImpl.java | 6 ++++++ .../geant/nmaas/portal/service/impl/UserServiceImpl.java | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/src/main/java/net/geant/nmaas/portal/service/DomainGroupService.java b/src/main/java/net/geant/nmaas/portal/service/DomainGroupService.java index a95e5c3c1..1bf54f5fc 100644 --- a/src/main/java/net/geant/nmaas/portal/service/DomainGroupService.java +++ b/src/main/java/net/geant/nmaas/portal/service/DomainGroupService.java @@ -3,6 +3,7 @@ package net.geant.nmaas.portal.service; import net.geant.nmaas.portal.api.domain.DomainGroupView; import net.geant.nmaas.portal.persistent.entity.ApplicationBase; import net.geant.nmaas.portal.persistent.entity.Domain; +import net.geant.nmaas.portal.persistent.entity.User; import java.util.List; @@ -26,4 +27,5 @@ public interface DomainGroupService { void deleteAppBaseFromAllAppState(ApplicationBase base); + void deleteUserFromAllDomainsGroups(User user); } diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/DomainGroupServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/DomainGroupServiceImpl.java index 32c7e7598..3dbc1baf9 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/DomainGroupServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/DomainGroupServiceImpl.java @@ -143,4 +143,10 @@ public class DomainGroupServiceImpl implements DomainGroupService { }); } + @Override + public void deleteUserFromAllDomainsGroups(User user) { + domainGroupRepository.findAll().forEach(d -> { + d.getManagers().remove(user); + }); + } } \ No newline at end of file diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/UserServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/UserServiceImpl.java index a4b8e58a3..71f881256 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/UserServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/UserServiceImpl.java @@ -17,12 +17,14 @@ import net.geant.nmaas.portal.api.exception.ProcessingException; import net.geant.nmaas.portal.api.exception.SignupException; import net.geant.nmaas.portal.api.security.JWTTokenService; import net.geant.nmaas.portal.persistent.entity.Domain; +import net.geant.nmaas.portal.persistent.entity.DomainGroup; import net.geant.nmaas.portal.persistent.entity.Role; import net.geant.nmaas.portal.persistent.entity.User; import net.geant.nmaas.portal.persistent.entity.UserRole; import net.geant.nmaas.portal.persistent.repositories.UserRepository; import net.geant.nmaas.portal.persistent.repositories.UserRoleRepository; import net.geant.nmaas.portal.service.ConfigurationManager; +import net.geant.nmaas.portal.service.DomainGroupService; import net.geant.nmaas.portal.service.UserService; import org.apache.commons.lang3.RandomStringUtils; import org.modelmapper.ModelMapper; @@ -58,6 +60,7 @@ public class UserServiceImpl implements UserService { private final ApplicationEventPublisher eventPublisher; private final JWTTokenService jwtTokenService; + private final DomainGroupService domainGroupService; @Value("${portal.address}") @Setter @@ -215,12 +218,14 @@ public class UserServiceImpl implements UserService { public void delete(User user) { checkParam(user); checkParam(user.getId()); + domainGroupService.deleteUserFromAllDomainsGroups(user); userRepository.delete(user); } @Override public void deleteById(Long userId) { checkParam(userId); + domainGroupService.deleteUserFromAllDomainsGroups(userRepository.getReferenceById(userId)); userRepository.deleteById(userId); } -- GitLab From 3602da60731906634b9977e47a6d8869ab962eb3 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Tue, 8 Oct 2024 12:38:59 +0200 Subject: [PATCH 34/50] update test --- .../nmaas/portal/service/impl/UserServiceImplTest.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/java/net/geant/nmaas/portal/service/impl/UserServiceImplTest.java b/src/test/java/net/geant/nmaas/portal/service/impl/UserServiceImplTest.java index 9ee91a674..81f94466b 100644 --- a/src/test/java/net/geant/nmaas/portal/service/impl/UserServiceImplTest.java +++ b/src/test/java/net/geant/nmaas/portal/service/impl/UserServiceImplTest.java @@ -14,6 +14,7 @@ import net.geant.nmaas.portal.persistent.entity.UserRole; import net.geant.nmaas.portal.persistent.repositories.UserRepository; import net.geant.nmaas.portal.persistent.repositories.UserRoleRepository; import net.geant.nmaas.portal.service.ConfigurationManager; +import net.geant.nmaas.portal.service.DomainGroupService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -57,11 +58,14 @@ public class UserServiceImplTest { @Mock JWTTokenService jwtTokenService; + @Mock + DomainGroupService domainGroupService; + UserServiceImpl userService; @BeforeEach void setup() { - userService = new UserServiceImpl(userRepository, userRoleRepository, new BCryptPasswordEncoder(), configurationManager, new ModelMapper(), eventPublisher, jwtTokenService); + userService = new UserServiceImpl(userRepository, userRoleRepository, new BCryptPasswordEncoder(), configurationManager, new ModelMapper(), eventPublisher, jwtTokenService,domainGroupService); userService.setPortalAddress("portalAddress"); } -- GitLab From accca020c1846eacf472eba4a743a5b72d673ece Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Tue, 8 Oct 2024 12:39:57 +0200 Subject: [PATCH 35/50] change name assign --- .../net/geant/nmaas/portal/service/impl/UserServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/geant/nmaas/portal/service/impl/UserServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/UserServiceImpl.java index 71f881256..eca382c54 100644 --- a/src/main/java/net/geant/nmaas/portal/service/impl/UserServiceImpl.java +++ b/src/main/java/net/geant/nmaas/portal/service/impl/UserServiceImpl.java @@ -183,6 +183,8 @@ public class UserServiceImpl implements UserService { newUser.setSelectedLanguage(configurationManager.getConfiguration().getDefaultLanguage()); newUser.setTermsOfUseAccepted(true); newUser.setPrivacyPolicyAccepted(true); + newUser.setFirstname(csvUser.getAdminUserName()); + newUser.setLastname(csvUser.getAdminUserName()); if (domain != null) { newUser.setNewRoles(ImmutableSet.of(new UserRole(newUser, domain, ROLE_DOMAIN_ADMIN))); } @@ -191,8 +193,6 @@ public class UserServiceImpl implements UserService { if (configurationManager.getConfiguration().isBulkDomainsAllowForSsoAccounts()) { if (csvUser.getSsoEnabled() != null && csvUser.getSsoEnabled()) { newUser.setSamlToken(csvUser.getEmail()); - newUser.setFirstname(csvUser.getAdminUserName()); - newUser.setLastname(csvUser.getAdminUserName()); if(sendMails) this.sendMail(newUser, MailType.NEW_BULK_SSO_LOGIN); }else { if(sendMails) this.sendMail(newUser, MailType.NEW_BULK_LOGIN); -- GitLab From 62a8a6ecd152b3fd63b8ce039ecb4d3e2f2fd1d8 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Thu, 10 Oct 2024 12:57:29 +0200 Subject: [PATCH 36/50] Add exception on templates --- .../templates/TemplateController.java | 9 +++++++++ .../templates/TemplateService.java | 18 ++++++++++++----- .../exceptions/DataConflictException.java | 20 +++++++++++++++++++ 3 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 src/main/java/net/geant/nmaas/portal/exceptions/DataConflictException.java 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 eb7360265..9483df6b8 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 bd5e37907..a94b007b3 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; @@ -15,6 +16,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import javax.annotation.CheckForNull; import java.io.File; import java.io.FileReader; import java.io.IOException; @@ -22,7 +24,7 @@ import java.util.List; import java.util.Objects; import java.util.stream.Collectors; -import static com.google.common.base.Preconditions.checkArgument; +//import static com.google.common.base.Preconditions.checkArgument; @Service public class TemplateService { @@ -42,7 +44,7 @@ public class TemplateService { @Transactional public MailTemplateView getMailTemplate(MailType mailType){ - MailTemplate mailTemplate = repository.findByMailType(mailType).orElseThrow(() -> new IllegalArgumentException("Mail template not found")); + MailTemplate mailTemplate = repository.findByMailType(mailType).orElseThrow(() -> new DataConflictException(String.format("Mail template %s not found", mailType.name() ))); return modelMapper.map(mailTemplate, MailTemplateView.class); } @@ -53,13 +55,13 @@ public class TemplateService { } void saveMailTemplate(MailTemplateView mailTemplate) { - checkArgument(!repository.existsByMailType(mailTemplate.getMailType()),"Mail template already exists"); + checkArgument(!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)); } void updateMailTemplate(MailTemplateView mailTemplate) { - MailTemplate mailTemplateEntity = repository.findByMailType(mailTemplate.getMailType()).orElseThrow(() -> new IllegalArgumentException("Mail template not found")); + MailTemplate mailTemplateEntity = repository.findByMailType(mailTemplate.getMailType()).orElseThrow(() -> new DataConflictException(String.format("Mail template %s not found", mailTemplate.getMailType().name() ))); checkArgument(mailTemplate.getTemplates() != null && !mailTemplate.getTemplates().isEmpty(), "Mail template cannot be null or empty"); mailTemplateEntity.getTemplates().clear(); mailTemplateEntity.getTemplates().addAll(mailTemplate.getTemplates().stream().map(template -> modelMapper.map(template, LanguageMailContent.class)).collect(Collectors.toList())); @@ -90,7 +92,13 @@ public class TemplateService { if (template.size() == 1) { return template.get(0); } - throw new IllegalArgumentException(String.format("Exactly one html template supported (actually got %d)", template.size())); + throw new DataConflictException(String.format("Exactly one html template supported (actually got %d)", template.size())); + } + + private static void checkArgument(boolean expression, String errorMessage) { + if (!expression) { + throw new DataConflictException(String.valueOf(errorMessage)); + } } } 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 000000000..e269f78cf --- /dev/null +++ b/src/main/java/net/geant/nmaas/portal/exceptions/DataConflictException.java @@ -0,0 +1,20 @@ +package net.geant.nmaas.portal.exceptions; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class DataConflictException extends RuntimeException { + + private String message; + public DataConflictException(String message) + { + super(message); + log.error("test ?????"); + this.message = message; + } + + public String getMsg() { + return message; + } + +} -- GitLab From 1d98751c1d9b1f3c69c88787d6ca97ac7111b8cf Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Thu, 10 Oct 2024 13:00:56 +0200 Subject: [PATCH 37/50] Add exception for contact types --- .../nmaas/notifications/types/FormTypeController.java | 7 +++++++ .../notifications/types/service/FormTypeService.java | 3 ++- .../nmaas/portal/exceptions/DataConflictException.java | 10 +--------- 3 files changed, 10 insertions(+), 10 deletions(-) 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 196e841f2..55172bac6 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 06e47911b..21426f5f5 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/portal/exceptions/DataConflictException.java b/src/main/java/net/geant/nmaas/portal/exceptions/DataConflictException.java index e269f78cf..aadb9107d 100644 --- a/src/main/java/net/geant/nmaas/portal/exceptions/DataConflictException.java +++ b/src/main/java/net/geant/nmaas/portal/exceptions/DataConflictException.java @@ -5,16 +5,8 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public class DataConflictException extends RuntimeException { - private String message; - public DataConflictException(String message) - { + public DataConflictException(String message) { super(message); - log.error("test ?????"); - this.message = message; - } - - public String getMsg() { - return message; } } -- GitLab From 7e3a3f94788e29bf400baeea8698168fd3f0b6e5 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Thu, 10 Oct 2024 14:16:00 +0200 Subject: [PATCH 38/50] Add new logic for translations --- .../api/auth/SSOAuthControllerIntTest.java | 2 +- .../i18n/InternationalizationController.java | 30 +++++++++----- .../exceptions/IllegalExceptionHandler.java | 31 --------------- .../service/InternationalizationService.java | 2 +- .../impl/InternationalizationServiceImpl.java | 39 ++++++++++++++++++- .../impl/InternationalizationServiceTest.java | 10 ++--- 6 files changed, 65 insertions(+), 49 deletions(-) delete mode 100644 src/main/java/net/geant/nmaas/portal/exceptions/IllegalExceptionHandler.java 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 46ff082c6..16867a493 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/main/java/net/geant/nmaas/portal/api/i18n/InternationalizationController.java b/src/main/java/net/geant/nmaas/portal/api/i18n/InternationalizationController.java index b15cbed12..2fb0cca6e 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/exceptions/IllegalExceptionHandler.java b/src/main/java/net/geant/nmaas/portal/exceptions/IllegalExceptionHandler.java deleted file mode 100644 index 983d4b3b9..000000000 --- a/src/main/java/net/geant/nmaas/portal/exceptions/IllegalExceptionHandler.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.geant.nmaas.portal.exceptions; - -import lombok.extern.slf4j.Slf4j; -import net.bytebuddy.pool.TypePool; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; - -@ControllerAdvice -@Slf4j -public class IllegalExceptionHandler { - - @ExceptionHandler(IllegalArgumentException.class) - public ResponseEntity<?> handle(IllegalArgumentException ex) { - log.error("Test throw ? "); - return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_ACCEPTABLE); - } - - @ExceptionHandler(IllegalStateException.class) - public ResponseEntity<?> handle(IllegalStateException ex) { - log.error("Test throw 2 ? "); - return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_ACCEPTABLE); - } - - @ExceptionHandler(RuntimeException.class) - public ResponseEntity<?> handle(RuntimeException ex) { - log.error("Test throw 3 ? "); - return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_ACCEPTABLE); - } -} 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 66a3e9a37..7806750f2 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/InternationalizationServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/InternationalizationServiceImpl.java index b114ad877..6916a916b 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,8 +2,10 @@ 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.exceptions.DataConflictException; import net.geant.nmaas.portal.persistent.entity.InternationalizationSimple; import net.geant.nmaas.portal.persistent.repositories.InternationalizationSimpleRepository; import net.geant.nmaas.portal.service.ConfigurationManager; @@ -14,11 +16,14 @@ import org.springframework.stereotype.Service; import javax.transaction.Transactional; 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,39 @@ 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 DataConflictException("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 overrideContent() { + } private void checkRequest(InternationalizationView newLanguage) { diff --git a/src/test/java/net/geant/nmaas/portal/service/impl/InternationalizationServiceTest.java b/src/test/java/net/geant/nmaas/portal/service/impl/InternationalizationServiceTest.java index 541e75c99..8306ed1ba 100644 --- a/src/test/java/net/geant/nmaas/portal/service/impl/InternationalizationServiceTest.java +++ b/src/test/java/net/geant/nmaas/portal/service/impl/InternationalizationServiceTest.java @@ -46,20 +46,20 @@ public class InternationalizationServiceTest { @Test public void shouldSaveLanguageContent(){ - internationalizationService.addNewLanguage(this.language); + internationalizationService.addNewLanguage(this.language, false); verify(repository, times(1)).save(any()); } @Test public void shouldNotSaveNullRequest(){ - assertThrows(IllegalArgumentException.class, ()-> internationalizationService.addNewLanguage(null)); + assertThrows(IllegalArgumentException.class, ()-> internationalizationService.addNewLanguage(null, false)); } @Test public void shouldNotSaveWithEmptyLanguageId(){ assertThrows(IllegalArgumentException.class, ()-> { this.language.setLanguage(""); - internationalizationService.addNewLanguage(this.language); + internationalizationService.addNewLanguage(this.language, false); }); } @@ -67,7 +67,7 @@ public class InternationalizationServiceTest { public void shouldNotSaveWithEmptyContent(){ assertThrows(IllegalArgumentException.class, ()-> { this.language.setContent(""); - internationalizationService.addNewLanguage(this.language); + internationalizationService.addNewLanguage(this.language, false); }); } @@ -75,7 +75,7 @@ public class InternationalizationServiceTest { public void shouldNotSaveWithInvalidJsonContent(){ assertThrows(IllegalArgumentException.class, ()-> { this.language.setContent("{invalid]"); - internationalizationService.addNewLanguage(this.language); + internationalizationService.addNewLanguage(this.language, false); }); } -- GitLab From 7491f7de1b41edde71c0c888b014b072b437dff1 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Thu, 10 Oct 2024 14:37:19 +0200 Subject: [PATCH 39/50] fix test --- .../notifications/templates/TemplateServiceTest.java | 11 ++++++----- .../types/service/FormTypeServiceTest.java | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) 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 ae36fb831..6f50f1e03 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; @@ -33,7 +34,7 @@ public class TemplateServiceTest { @Test void shouldThrowExceptionOnMissingHtmlTemplate() { - assertThrows(IllegalArgumentException.class, () -> { + assertThrows(DataConflictException.class, () -> { templateService.getHTMLTemplate(); }); } @@ -52,17 +53,17 @@ public class TemplateServiceTest { when(repository.findByMailType(MailType.ACCOUNT_ACTIVATED)) .thenReturn(Optional.of(new MailTemplate(1L, MailType.ACCOUNT_ACTIVATED, null, null))); assertNotNull(templateService.getMailTemplate(MailType.ACCOUNT_ACTIVATED)); - assertThrows(IllegalArgumentException.class, () -> { + assertThrows(DataConflictException.class, () -> { templateService.getMailTemplate(MailType.ACCOUNT_BLOCKED); }); } @Test void shouldHandleHtmlTemplateStorage() { - assertThrows(IllegalArgumentException.class, () -> { + assertThrows(DataConflictException.class, () -> { templateService.storeHTMLTemplate(null); }); - assertThrows(IllegalArgumentException.class, () -> { + assertThrows(DataConflictException.class, () -> { templateService.storeHTMLTemplate(new MockMultipartFile("name", "content".getBytes())); }); assertDoesNotThrow(() -> { @@ -72,7 +73,7 @@ public class TemplateServiceTest { @Test void shouldUpdateHtmlTemplate() { - assertThrows(IllegalArgumentException.class, () -> { + assertThrows(DataConflictException.class, () -> { templateService.updateHTMLTemplate(null); }); } 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 2f78bed75..550c228e7 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)); } -- GitLab From 9ff30c19c95cd6469f07d902fae714bf669809e3 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Thu, 10 Oct 2024 15:03:29 +0200 Subject: [PATCH 40/50] delete imports --- .../notifications/templates/TemplateService.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) 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 a94b007b3..0007dc83e 100644 --- a/src/main/java/net/geant/nmaas/notifications/templates/TemplateService.java +++ b/src/main/java/net/geant/nmaas/notifications/templates/TemplateService.java @@ -16,7 +16,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; -import javax.annotation.CheckForNull; import java.io.File; import java.io.FileReader; import java.io.IOException; @@ -24,7 +23,6 @@ import java.util.List; import java.util.Objects; import java.util.stream.Collectors; -//import static com.google.common.base.Preconditions.checkArgument; @Service public class TemplateService { @@ -36,32 +34,32 @@ 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){ - MailTemplate mailTemplate = repository.findByMailType(mailType).orElseThrow(() -> new DataConflictException(String.format("Mail template %s not found", mailType.name() ))); + public MailTemplateView getMailTemplate(MailType mailType) { + MailTemplate mailTemplate = repository.findByMailType(mailType).orElseThrow(() -> new DataConflictException(String.format("Mail template %s not found", mailType.name()))); 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()), String.format("Mail template %s already exists", mailTemplate.getMailType().name() )); + checkArgument(!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)); } void updateMailTemplate(MailTemplateView mailTemplate) { - MailTemplate mailTemplateEntity = repository.findByMailType(mailTemplate.getMailType()).orElseThrow(() -> new DataConflictException(String.format("Mail template %s not found", mailTemplate.getMailType().name() ))); + MailTemplate mailTemplateEntity = repository.findByMailType(mailTemplate.getMailType()).orElseThrow(() -> new DataConflictException(String.format("Mail template %s not found", mailTemplate.getMailType().name()))); checkArgument(mailTemplate.getTemplates() != null && !mailTemplate.getTemplates().isEmpty(), "Mail template cannot be null or empty"); mailTemplateEntity.getTemplates().clear(); mailTemplateEntity.getTemplates().addAll(mailTemplate.getTemplates().stream().map(template -> modelMapper.map(template, LanguageMailContent.class)).collect(Collectors.toList())); @@ -75,7 +73,7 @@ public class TemplateService { fileStorageService.store(file); } - void updateHTMLTemplate(MultipartFile file){ + void updateHTMLTemplate(MultipartFile file) { FileInfo fileInfo = getHTMLTemplateFileInfo(); if (fileStorageService.remove(fileInfo)) { storeHTMLTemplate(file); -- GitLab From 5303a41a5cf9ad9f0283066300cc5f19a6b663df Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Wed, 23 Oct 2024 11:19:15 +0200 Subject: [PATCH 41/50] update exception type --- .../nmaas/notifications/templates/TemplateService.java | 6 +++--- .../service/impl/InternationalizationServiceImpl.java | 7 ++----- 2 files changed, 5 insertions(+), 8 deletions(-) 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 0007dc83e..632c57c83 100644 --- a/src/main/java/net/geant/nmaas/notifications/templates/TemplateService.java +++ b/src/main/java/net/geant/nmaas/notifications/templates/TemplateService.java @@ -42,7 +42,7 @@ public class TemplateService { @Transactional public MailTemplateView getMailTemplate(MailType mailType) { - MailTemplate mailTemplate = repository.findByMailType(mailType).orElseThrow(() -> new DataConflictException(String.format("Mail template %s not found", mailType.name()))); + MailTemplate mailTemplate = repository.findByMailType(mailType).orElseThrow(() -> new IllegalArgumentException("Mail template not found")); return modelMapper.map(mailTemplate, MailTemplateView.class); } @@ -59,7 +59,7 @@ public class TemplateService { } void updateMailTemplate(MailTemplateView mailTemplate) { - MailTemplate mailTemplateEntity = repository.findByMailType(mailTemplate.getMailType()).orElseThrow(() -> new DataConflictException(String.format("Mail template %s not found", mailTemplate.getMailType().name()))); + MailTemplate mailTemplateEntity = repository.findByMailType(mailTemplate.getMailType()).orElseThrow(() -> new IllegalArgumentException("Mail template not found")); checkArgument(mailTemplate.getTemplates() != null && !mailTemplate.getTemplates().isEmpty(), "Mail template cannot be null or empty"); mailTemplateEntity.getTemplates().clear(); mailTemplateEntity.getTemplates().addAll(mailTemplate.getTemplates().stream().map(template -> modelMapper.map(template, LanguageMailContent.class)).collect(Collectors.toList())); @@ -90,7 +90,7 @@ public class TemplateService { if (template.size() == 1) { return template.get(0); } - throw new DataConflictException(String.format("Exactly one html template supported (actually got %d)", template.size())); + throw new IllegalArgumentException(String.format("Exactly one html template supported (actually got %d)", template.size())); } private static void checkArgument(boolean expression, String errorMessage) { 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 6916a916b..9b76a37eb 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 @@ -15,6 +15,7 @@ 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; @@ -37,7 +38,7 @@ public class InternationalizationServiceImpl implements InternationalizationServ repository.save(newLanguage.getAsInternationalizationSimple()); } else { //add empty or override - InternationalizationSimple is = repository.findByLanguageOrderByIdDesc(newLanguage.getLanguage()).orElseThrow(() -> new DataConflictException("Language not found")); + InternationalizationSimple is = repository.findByLanguageOrderByIdDesc(newLanguage.getLanguage()).orElseThrow(() -> new NotFoundException("Language not found")); InternationalizationView iv = is.getAsInternationalizationView(); if (!force) { @@ -62,10 +63,6 @@ public class InternationalizationServiceImpl implements InternationalizationServ } } - private void overrideContent() { - - } - private void checkRequest(InternationalizationView newLanguage) { if (newLanguage == null) { throw new IllegalArgumentException("Language cannot be null"); -- GitLab From 4d60186ef4c577b081d084e6bf1df196e612fae2 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Wed, 23 Oct 2024 12:05:07 +0200 Subject: [PATCH 42/50] Add constraint on user on BulkDeployment --- .../geant/nmaas/portal/api/bulk/BulkController.java | 12 ++++++------ .../portal/persistent/entity/BulkDeployment.java | 6 +++++- .../service/impl/BulkApplicationServiceImpl.java | 6 ++++-- .../portal/service/impl/BulkDomainServiceImpl.java | 4 ++-- ...23_1200__addContraintOnUserIdInBulkDeployment.sql | 4 ++++ 5 files changed, 21 insertions(+), 11 deletions(-) create mode 100644 src/main/resources/db/migration/common/V1.7.0_20241023_1200__addContraintOnUserIdInBulkDeployment.sql 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 dc3629c55..517827788 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 @@ -110,7 +110,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); @@ -165,7 +165,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) { @@ -196,9 +196,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); @@ -208,10 +208,10 @@ public class BulkController { private BulkDeploymentView mapToView(BulkDeployment deployment) { BulkDeploymentView bulkView = modelMapper.map(deployment, BulkDeploymentView.class); try { - bulkView.setCreator(getUserView(deployment.getCreatorId())); + bulkView.setCreator(getUserView(deployment.getCreator().getId())); return null; } catch (Exception ex) { - log.error("Can not find creator for {} - creatorId: {}", deployment.getId(), deployment.getCreatorId()); + log.error("Can not find creator for {} - creatorId: {}", deployment.getId(), deployment.getCreator().getId()); } mapDetails(deployment, bulkView); return bulkView; 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 9d3357fc9..06a9a0b9f 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/service/impl/BulkApplicationServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/BulkApplicationServiceImpl.java index c7e5ae6c4..2e4dd2e92 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; @@ -372,11 +374,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 5c9315950..fa2512fbd 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/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 000000000..df08df98f --- /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 -- GitLab From f16b167215c4df4a48bf90bffb602c054c6e21d0 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Wed, 23 Oct 2024 12:24:24 +0200 Subject: [PATCH 43/50] Update test --- .../service/impl/BulkDomainServiceIntTest.java | 6 +++--- .../portal/api/bulk/BulkControllerTest.java | 6 +++--- .../impl/BulkApplicationServiceImplTest.java | 17 +++++++++++++---- .../service/impl/BulkDomainServiceImplTest.java | 11 +++++++---- 4 files changed, 26 insertions(+), 14 deletions(-) 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 391174b49..80ab22b6c 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/test/java/net/geant/nmaas/portal/api/bulk/BulkControllerTest.java b/src/test/java/net/geant/nmaas/portal/api/bulk/BulkControllerTest.java index 55fe03f48..02fa1407e 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/BulkApplicationServiceImplTest.java b/src/test/java/net/geant/nmaas/portal/service/impl/BulkApplicationServiceImplTest.java index 02909dad0..1d9f08617 100644 --- a/src/test/java/net/geant/nmaas/portal/service/impl/BulkApplicationServiceImplTest.java +++ b/src/test/java/net/geant/nmaas/portal/service/impl/BulkApplicationServiceImplTest.java @@ -19,6 +19,7 @@ import net.geant.nmaas.portal.persistent.entity.BulkDeployment; import net.geant.nmaas.portal.persistent.entity.BulkDeploymentEntry; import net.geant.nmaas.portal.persistent.entity.BulkDeploymentState; import net.geant.nmaas.portal.persistent.entity.Domain; +import net.geant.nmaas.portal.persistent.entity.User; import net.geant.nmaas.portal.persistent.repositories.BulkDeploymentEntryRepository; import net.geant.nmaas.portal.persistent.repositories.BulkDeploymentRepository; import net.geant.nmaas.portal.service.ApplicationBaseService; @@ -27,6 +28,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.multimap.HashSetValuedHashMap; import org.junit.jupiter.api.Test; import org.mockito.AdditionalAnswers; @@ -70,11 +72,13 @@ public class BulkApplicationServiceImplTest { private final AppLifecycleManager appLifecycleManager = mock(AppLifecycleManager.class); private final BulkDeploymentRepository bulkDeploymentRepository = mock(BulkDeploymentRepository.class); private final BulkDeploymentEntryRepository bulkDeploymentEntryRepository = mock(BulkDeploymentEntryRepository.class); + + private final UserService userService = mock(UserService.class); private final ModelMapper modelMapper = new ModelMapper(); private final ApplicationEventPublisher eventPublisher = mock(ApplicationEventPublisher.class); final BulkApplicationService bulkApplicationService = new BulkApplicationServiceImpl(applicationBaseService, applicationService, - domainService, applicationSubscriptionService, applicationInstanceService, appDeploymentMonitor, appLifecycleManager, + domainService, applicationSubscriptionService,userService, applicationInstanceService, appDeploymentMonitor, appLifecycleManager, bulkDeploymentRepository, bulkDeploymentEntryRepository, modelMapper, eventPublisher); @Test @@ -98,6 +102,9 @@ public class BulkApplicationServiceImplTest { when(bulkDeploymentEntryRepository.save(any(BulkDeploymentEntry.class))).then(AdditionalAnswers.returnsFirstArg()); when(bulkDeploymentRepository.save(any(BulkDeployment.class))).thenReturn(new BulkDeployment()); doNothing().when(eventPublisher).publishEvent(any(ApplicationEvent.class)); + User user =new User("Test"); + user.setId(1L); + when(userService.findById(any())).thenReturn(Optional.of(user)); bulkApplicationService.handleBulkDeployment(TEST_APP_NAME, List.of(csvApplication), testUser()); @@ -116,7 +123,7 @@ public class BulkApplicationServiceImplTest { BulkDeployment bulkDeployment = bulkDeploymentArgumentCaptor.getValue(); assertEquals(PROCESSING, bulkDeployment.getState()); assertEquals(APPLICATION, bulkDeployment.getType()); - assertEquals(testUser().getId(), bulkDeployment.getCreatorId()); + assertEquals(testUser().getId(), bulkDeployment.getCreator().getId()); assertEquals(1, bulkDeployment.getEntries().size()); assertEquals(PROCESSING, bulkDeployment.getEntries().get(0).getState()); } @@ -175,11 +182,13 @@ public class BulkApplicationServiceImplTest { @Test void shouldHandleDeploymentReview() { AppAutoDeploymentReviewEvent event = new AppAutoDeploymentReviewEvent(this); + User user = new User("Test"); + user.setId(1L); BulkDeployment bAppToBeCompleted = new BulkDeployment( - 1L, 1L, OffsetDateTime.now(), PROCESSING, APPLICATION, + 1L, user, OffsetDateTime.now(), PROCESSING, APPLICATION, new ArrayList<>(List.of(new BulkDeploymentEntry(10L, APPLICATION, COMPLETED, true, null)))); BulkDeployment bAppProcessing = new BulkDeployment( - 2L, 1L, OffsetDateTime.now(), PROCESSING, APPLICATION, + 2L, user, OffsetDateTime.now(), PROCESSING, APPLICATION, new ArrayList<>(List.of(new BulkDeploymentEntry(11L, APPLICATION, PROCESSING, true, null)))); when(bulkDeploymentRepository.findByTypeAndState(APPLICATION, PROCESSING)) .thenReturn(List.of(bAppToBeCompleted, bAppProcessing)); 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 1b6b7b62f..a110e99b8 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() { -- GitLab From 563bde8aa10b04ee38bcff75a1386a0f26f30076 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Thu, 24 Oct 2024 12:14:41 +0200 Subject: [PATCH 44/50] Update domain groups --- .../portal/api/market/DomainController.java | 14 ++++++++++++++ .../nmaas/portal/service/DomainService.java | 3 +++ .../service/impl/DomainServiceImpl.java | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+) 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 382d56837..36707803c 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/service/DomainService.java b/src/main/java/net/geant/nmaas/portal/service/DomainService.java index 70ff8d5da..a26f3b60c 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/impl/DomainServiceImpl.java b/src/main/java/net/geant/nmaas/portal/service/impl/DomainServiceImpl.java index 0caa03568..98c8a5391 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 -- GitLab From 83be806aef53c58ee31be3c4fc3c95de9a692073 Mon Sep 17 00:00:00 2001 From: llopat <llopat@man.poznan.pl> Date: Thu, 24 Oct 2024 12:37:08 +0200 Subject: [PATCH 45/50] Fix after merge --- .../geant/nmaas/portal/service/BulkApplicationService.java | 4 ---- 1 file changed, 4 deletions(-) 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 080c4f27e..53dc4336c 100644 --- a/src/main/java/net/geant/nmaas/portal/service/BulkApplicationService.java +++ b/src/main/java/net/geant/nmaas/portal/service/BulkApplicationService.java @@ -29,8 +29,4 @@ public interface BulkApplicationService { BulkDeployment updateState(Long bulkId); - void deleteAppInstancesFromBulk(BulkDeploymentView bulk); - - BulkDeployment updateState(Long bulkId); - } \ No newline at end of file -- GitLab From d186804132719e7fe8447ba2ba26a040f4184556 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Thu, 24 Oct 2024 13:14:16 +0200 Subject: [PATCH 46/50] update thrown exception --- .../nmaas/notifications/templates/TemplateService.java | 8 +++++--- .../notifications/templates/TemplateServiceTest.java | 10 +++++----- 2 files changed, 10 insertions(+), 8 deletions(-) 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 632c57c83..8f8cb8d92 100644 --- a/src/main/java/net/geant/nmaas/notifications/templates/TemplateService.java +++ b/src/main/java/net/geant/nmaas/notifications/templates/TemplateService.java @@ -23,6 +23,8 @@ import java.util.List; import java.util.Objects; import java.util.stream.Collectors; +import static com.google.common.base.Preconditions.checkArgument; + @Service public class TemplateService { @@ -53,7 +55,7 @@ public class TemplateService { } void saveMailTemplate(MailTemplateView mailTemplate) { - checkArgument(!repository.existsByMailType(mailTemplate.getMailType()), String.format("Mail template %s already exists", mailTemplate.getMailType().name())); + 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,7 +71,7 @@ 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); } @@ -93,7 +95,7 @@ public class TemplateService { throw new IllegalArgumentException(String.format("Exactly one html template supported (actually got %d)", template.size())); } - private static void checkArgument(boolean expression, String errorMessage) { + private static void checkArgumentConflict(boolean expression, String errorMessage) { if (!expression) { throw new DataConflictException(String.valueOf(errorMessage)); } 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 6f50f1e03..02b79cdc8 100644 --- a/src/test/java/net/geant/nmaas/notifications/templates/TemplateServiceTest.java +++ b/src/test/java/net/geant/nmaas/notifications/templates/TemplateServiceTest.java @@ -34,7 +34,7 @@ public class TemplateServiceTest { @Test void shouldThrowExceptionOnMissingHtmlTemplate() { - assertThrows(DataConflictException.class, () -> { + assertThrows(IllegalArgumentException.class, () -> { templateService.getHTMLTemplate(); }); } @@ -53,17 +53,17 @@ public class TemplateServiceTest { when(repository.findByMailType(MailType.ACCOUNT_ACTIVATED)) .thenReturn(Optional.of(new MailTemplate(1L, MailType.ACCOUNT_ACTIVATED, null, null))); assertNotNull(templateService.getMailTemplate(MailType.ACCOUNT_ACTIVATED)); - assertThrows(DataConflictException.class, () -> { + assertThrows(IllegalArgumentException.class, () -> { templateService.getMailTemplate(MailType.ACCOUNT_BLOCKED); }); } @Test void shouldHandleHtmlTemplateStorage() { - assertThrows(DataConflictException.class, () -> { + assertThrows(IllegalArgumentException.class, () -> { templateService.storeHTMLTemplate(null); }); - assertThrows(DataConflictException.class, () -> { + assertThrows(IllegalArgumentException.class, () -> { templateService.storeHTMLTemplate(new MockMultipartFile("name", "content".getBytes())); }); assertDoesNotThrow(() -> { @@ -73,7 +73,7 @@ public class TemplateServiceTest { @Test void shouldUpdateHtmlTemplate() { - assertThrows(DataConflictException.class, () -> { + assertThrows(IllegalArgumentException.class, () -> { templateService.updateHTMLTemplate(null); }); } -- GitLab From cd74d1753280b0e8139f01f56c5bebc5e02d5184 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Wed, 30 Oct 2024 15:45:16 +0100 Subject: [PATCH 47/50] Add test for members --- .../service/impl/DomainServiceTest.java | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) 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 e9e2e9922..f0cbfabbf 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 @@ -8,10 +8,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; @@ -488,7 +491,108 @@ 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); + + User user = new User("user"); + + + DomainGroupView domainGroupView = new DomainGroupView(1l, "test", "test1",List.of(domain1), null, List.of(userView) ); + 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); + + User user = new User("user"); + + + DomainGroupView domainGroupView = new DomainGroupView(1l, "test", "test1",List.of(domain1), null, List.of(userView) ); + 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); + + User user = new User("user"); + + + DomainGroupView domainGroupView = new DomainGroupView(1l, "test", "test1",List.of(domain1), null, List.of(userView) ); + 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()); } } -- GitLab From 4834295a874fb379104c7475af59888eba2e31c6 Mon Sep 17 00:00:00 2001 From: llopat <llopat@man.poznan.pl> Date: Thu, 31 Oct 2024 14:36:58 +0100 Subject: [PATCH 48/50] Minor updates in tests --- .../impl/InternationalizationServiceImpl.java | 1 - .../impl/ApplicationBaseServiceTest.java | 4 +- .../service/impl/DomainServiceTest.java | 39 +++++-------- .../impl/InternationalizationServiceTest.java | 58 +++++++++---------- .../service/impl/SSHKeyServiceTest.java | 29 +++++----- 5 files changed, 57 insertions(+), 74 deletions(-) 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 9b76a37eb..bd27ed1ff 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 @@ -5,7 +5,6 @@ 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.exceptions.DataConflictException; import net.geant.nmaas.portal.persistent.entity.InternationalizationSimple; import net.geant.nmaas.portal.persistent.repositories.InternationalizationSimpleRepository; import net.geant.nmaas.portal.service.ConfigurationManager; 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 30f8865e9..e62ab1503 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/DomainServiceTest.java b/src/test/java/net/geant/nmaas/portal/service/impl/DomainServiceTest.java index f0cbfabbf..c997d0800 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; @@ -58,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; @@ -249,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()); } @@ -382,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); @@ -490,7 +491,6 @@ public class DomainServiceTest { assertEquals(0, domainGroup.getApplicationStatePerDomain().size()); assertEquals(0, domainGroup2.getApplicationStatePerDomain().size()); - } @Test @@ -510,23 +510,18 @@ public class DomainServiceTest { 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"); - - - DomainGroupView domainGroupView = new DomainGroupView(1l, "test", "test1",List.of(domain1), null, List.of(userView) ); - DomainGroup domainGroup = new DomainGroup(1l, "test", "test1"); + 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 @@ -547,16 +542,12 @@ public class DomainServiceTest { 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"); - - - DomainGroupView domainGroupView = new DomainGroupView(1l, "test", "test1",List.of(domain1), null, List.of(userView) ); - DomainGroup domainGroup = new DomainGroup(1l, "test", "test1"); + 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()); @@ -580,16 +571,12 @@ public class DomainServiceTest { 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"); - - - DomainGroupView domainGroupView = new DomainGroupView(1l, "test", "test1",List.of(domain1), null, List.of(userView) ); - DomainGroup domainGroup = new DomainGroup(1l, "test", "test1"); + 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/InternationalizationServiceTest.java b/src/test/java/net/geant/nmaas/portal/service/impl/InternationalizationServiceTest.java index 8306ed1ba..d92954444 100644 --- a/src/test/java/net/geant/nmaas/portal/service/impl/InternationalizationServiceTest.java +++ b/src/test/java/net/geant/nmaas/portal/service/impl/InternationalizationServiceTest.java @@ -26,37 +26,34 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -public class InternationalizationServiceTest { +class InternationalizationServiceTest { - private InternationalizationSimpleRepository repository = mock(InternationalizationSimpleRepository.class); - - private ConfigurationManager configurationManager = mock(ConfigurationManager.class); - - private ModelMapper modelMapper = new ModelMapper(); + private final InternationalizationSimpleRepository repository = mock(InternationalizationSimpleRepository.class); + private final ConfigurationManager configurationManager = mock(ConfigurationManager.class); + private final ModelMapper modelMapper = new ModelMapper(); private InternationalizationService internationalizationService; - private InternationalizationView language; @BeforeEach - public void setup(){ + void setup(){ this.internationalizationService = new InternationalizationServiceImpl(repository, configurationManager, modelMapper); this.language = new InternationalizationView("pl", true, "{}"); } @Test - public void shouldSaveLanguageContent(){ + void shouldSaveLanguageContent() { internationalizationService.addNewLanguage(this.language, false); verify(repository, times(1)).save(any()); } @Test - public void shouldNotSaveNullRequest(){ + void shouldNotSaveNullRequest() { assertThrows(IllegalArgumentException.class, ()-> internationalizationService.addNewLanguage(null, false)); } @Test - public void shouldNotSaveWithEmptyLanguageId(){ + void shouldNotSaveWithEmptyLanguageId() { assertThrows(IllegalArgumentException.class, ()-> { this.language.setLanguage(""); internationalizationService.addNewLanguage(this.language, false); @@ -64,7 +61,7 @@ public class InternationalizationServiceTest { } @Test - public void shouldNotSaveWithEmptyContent(){ + void shouldNotSaveWithEmptyContent() { assertThrows(IllegalArgumentException.class, ()-> { this.language.setContent(""); internationalizationService.addNewLanguage(this.language, false); @@ -72,15 +69,15 @@ public class InternationalizationServiceTest { } @Test - public void shouldNotSaveWithInvalidJsonContent(){ - assertThrows(IllegalArgumentException.class, ()-> { + void shouldNotSaveWithInvalidJsonContent() { + assertThrows(IllegalArgumentException.class, () -> { this.language.setContent("{invalid]"); internationalizationService.addNewLanguage(this.language, false); }); } @Test - public void shouldGetAllSupportedLanguages(){ + void shouldGetAllSupportedLanguages() { when(repository.findAll()).thenReturn(Collections.singletonList(new InternationalizationView( "pl", true, "{\"test\":\"content\"}").getAsInternationalizationSimple())); List<InternationalizationBriefView> languageList = internationalizationService.getAllSupportedLanguages(); assertEquals(1, languageList.size()); @@ -89,14 +86,14 @@ public class InternationalizationServiceTest { } @Test - public void shouldReturnEmptyList(){ + void shouldReturnEmptyList() { when(repository.findAll()).thenReturn(Collections.emptyList()); List<InternationalizationBriefView> languageList = internationalizationService.getAllSupportedLanguages(); assertTrue(languageList.isEmpty()); } @Test - public void shouldChangeLanguageState(){ + void shouldChangeLanguageState() { when(configurationManager.getConfiguration()).thenReturn(new ConfigurationView(false, false, "fr", false, false, new ArrayList<>(), false, false)); InternationalizationView internationalization = new InternationalizationView("pl", false, "{\"test\":\"content\"}"); when(repository.findByLanguageOrderByIdDesc(language.getLanguage())).thenReturn(Optional.of(internationalization.getAsInternationalizationSimple())); @@ -105,7 +102,7 @@ public class InternationalizationServiceTest { } @Test - public void shouldThrowAnExceptionWhenLanguageIsNotFound(){ + void shouldThrowAnExceptionWhenLanguageIsNotFound() { assertThrows(IllegalArgumentException.class, () -> { when(repository.findByLanguageOrderByIdDesc(language.getLanguage())).thenReturn(Optional.empty()); internationalizationService.changeLanguageState(language); @@ -113,7 +110,7 @@ public class InternationalizationServiceTest { } @Test - public void shouldThrowAnExceptionWhenDisablingDefaultLanguage(){ + void shouldThrowAnExceptionWhenDisablingDefaultLanguage() { assertThrows(IllegalStateException.class, () -> { InternationalizationView internationalization = new InternationalizationView("pl", false, "{\"test\":\"content\"}"); when(repository.findByLanguageOrderByIdDesc(language.getLanguage())).thenReturn(Optional.of(internationalization.getAsInternationalizationSimple())); @@ -123,14 +120,14 @@ public class InternationalizationServiceTest { } @Test - public void shouldGetLanguageContent(){ + void shouldGetLanguageContent() { InternationalizationView internationalization = new InternationalizationView("pl", true, "{\"test\":\"content\"}"); when(repository.findByLanguageOrderByIdDesc("pl")).thenReturn(Optional.of(internationalization.getAsInternationalizationSimple())); assertEquals(internationalization.getContent(), internationalizationService.getLanguageContent("pl")); } @Test - public void shouldThrowAnExceptionWhenLanguageIsNotAvailable(){ + void shouldThrowAnExceptionWhenLanguageIsNotAvailable() { assertThrows(IllegalStateException.class, () -> { when(repository.findByLanguageOrderByIdDesc(any())).thenReturn(Optional.empty()); internationalizationService.getLanguageContent("pl"); @@ -138,7 +135,7 @@ public class InternationalizationServiceTest { } @Test - public void shouldReturnEnabledLanguages(){ + void shouldReturnEnabledLanguages() { when(repository.findAll()).thenReturn(Collections.singletonList(new InternationalizationView("pl", true, "{\"test\":\"content\"}").getAsInternationalizationSimple())); List<String> result = this.internationalizationService.getEnabledLanguages(); assertEquals(1, result.size()); @@ -146,46 +143,45 @@ public class InternationalizationServiceTest { } @Test - public void shouldReturnEmptyListWhenAllLanguagesDisabled(){ + void shouldReturnEmptyListWhenAllLanguagesDisabled() { when(repository.findAll()).thenReturn(Collections.singletonList(new InternationalizationView("pl", false, "{\"test\":\"content\"}").getAsInternationalizationSimple())); List<String> result = this.internationalizationService.getEnabledLanguages(); assertEquals(0, result.size()); } @Test - void shouldUpdateLanguage(){ + void shouldUpdateLanguage() { when(repository.findByLanguageOrderByIdDesc(anyString())).thenReturn(Optional.of(new InternationalizationView("pl", true, "{\"test\":\"content\"}").getAsInternationalizationSimple())); this.internationalizationService.updateLanguage("pl", "{\"test\":\"new-content\"}"); verify(repository, times(1)).save(any()); } @Test - void shouldNotUpdateLanguageWhenLangIsEmpty(){ + void shouldNotUpdateLanguageWhenLangIsEmpty() { when(repository.findByLanguageOrderByIdDesc(anyString())).thenReturn(Optional.of(new InternationalizationView("pl", true, "{\"test\":\"content\"}").getAsInternationalizationSimple())); assertThrows(IllegalArgumentException.class, () -> this.internationalizationService.updateLanguage("", "{\"test\":\"new-content\"}")); -; } @Test - void shouldNotUpdateLanguageWhenContentIsEmpty(){ + void shouldNotUpdateLanguageWhenContentIsEmpty() { when(repository.findByLanguageOrderByIdDesc(anyString())).thenReturn(Optional.of(new InternationalizationView("pl", true, "{\"test\":\"content\"}").getAsInternationalizationSimple())); assertThrows(IllegalArgumentException.class, () -> this.internationalizationService.updateLanguage("pl", "")); } @Test - void shouldNotUpdateLanguageWhenContentIsNotValidJson(){ + void shouldNotUpdateLanguageWhenContentIsNotValidJson() { when(repository.findByLanguageOrderByIdDesc(anyString())).thenReturn(Optional.of(new InternationalizationView("pl", true, "{\"test\":\"content\"}").getAsInternationalizationSimple())); assertThrows(IllegalArgumentException.class, () -> this.internationalizationService.updateLanguage("pl", "{\"test\":\"new-content\"")); } @Test - void shouldNotUpdateLanguageWhenLangIsNotFound(){ + void shouldNotUpdateLanguageWhenLangIsNotFound() { when(repository.findByLanguageOrderByIdDesc(anyString())).thenReturn(Optional.empty()); assertThrows(IllegalArgumentException.class, () -> this.internationalizationService.updateLanguage("pl", "{\"test\":\"new-content\"}")); } @Test - void shouldGetLanguage(){ + void shouldGetLanguage() { when(repository.findByLanguageOrderByIdDesc(anyString())).thenReturn(Optional.of(new InternationalizationView("pl", true, "{\"test\":\"content\"}").getAsInternationalizationSimple())); InternationalizationView langView = internationalizationService.getLanguage("pl"); assertEquals("pl", langView.getLanguage()); @@ -193,7 +189,7 @@ public class InternationalizationServiceTest { } @Test - void shouldNotGetLanguageWhenLangIsNotExists(){ + void shouldNotGetLanguageWhenLangIsNotExists() { when(repository.findByLanguageOrderByIdDesc(anyString())).thenReturn(Optional.empty()); assertThrows(IllegalArgumentException.class, () -> this.internationalizationService.getLanguage("pl")); } 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 09ff0e37d..fbf9baf42 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()); } + } -- GitLab From 33a21813acb5df3c874fa1fd30f406aa91d7c2bb Mon Sep 17 00:00:00 2001 From: llopat <llopat@man.poznan.pl> Date: Thu, 31 Oct 2024 14:37:46 +0100 Subject: [PATCH 49/50] Fixed sonar coverage --- .gitlab-ci.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a65ff76ac..f59a90d23 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 -- GitLab From df228debdbd681fd6c9fd73c4b762ffcbbd11cb3 Mon Sep 17 00:00:00 2001 From: kbeyro <121854496+kbeyro@users.noreply.github.com> Date: Thu, 19 Dec 2024 12:49:28 +0100 Subject: [PATCH 50/50] fix entry state processing --- .../portal/service/impl/BulkApplicationServiceImpl.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 d2b6a4111..f57db19e3 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 @@ -342,9 +342,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 -- GitLab