diff --git a/build.gradle b/build.gradle
index ba4062fd127dfe6302a9397e3d1c0b653a9ff1da..3a0d07daa528b359046eeb9a763d3397dd99b823 100644
--- a/build.gradle
+++ b/build.gradle
@@ -13,7 +13,7 @@ repositories {
mavenCentral()
}
-version = '1.6.3-SNAPSHOT'
+version = '1.7.0-SNAPSHOT'
group = 'net.geant.nmaas'
java {
diff --git a/src/main/java/net/geant/nmaas/notifications/NotificationController.java b/src/main/java/net/geant/nmaas/notifications/NotificationController.java
index 479709ca7e41fbcb2f1982131a3ba2c7de897879..762740d7c4e176ae4899267ace857a461e4ee268 100644
--- a/src/main/java/net/geant/nmaas/notifications/NotificationController.java
+++ b/src/main/java/net/geant/nmaas/notifications/NotificationController.java
@@ -31,7 +31,7 @@ public class NotificationController {
// TODO verify if captcha token must be verified
MailType mailType = mailAttributes.getMailType();
- if(mailType.equals(MailType.CONTACT_FORM) || mailType.equals(MailType.ISSUE_REPORT) || mailType.equals(MailType.NEW_DOMAIN_REQUEST)) {
+ if (mailType.equals(MailType.CONTACT_FORM) || mailType.equals(MailType.ISSUE_REPORT) || mailType.equals(MailType.NEW_DOMAIN_REQUEST)) {
eventPublisher.publishEvent(new NotificationEvent(this, mailAttributes));
} else {
throw new AuthenticationException("You are not allowed to send this mail");
diff --git a/src/main/java/net/geant/nmaas/notifications/NotificationManager.java b/src/main/java/net/geant/nmaas/notifications/NotificationManager.java
index 401a06eff27c9af5acb55971e2a36c494347a66c..ad62a89f3520b7a159ff5c70293faba432531cf3 100644
--- a/src/main/java/net/geant/nmaas/notifications/NotificationManager.java
+++ b/src/main/java/net/geant/nmaas/notifications/NotificationManager.java
@@ -70,7 +70,7 @@ public class NotificationManager {
try {
template = templateService.getHTMLTemplate();
} catch (IOException e) {
- log.error(String.format("Cannot retrieve html template: %s", e.getMessage()));
+ log.error("Cannot retrieve html template: {}", e.getMessage());
throw new ProcessingException(e);
}
@@ -193,7 +193,7 @@ public class NotificationManager {
}
private String getFilledTemplate(Template template, LanguageMailContentView langContent, UserView user, MailAttributes mailAttributes, MailTemplateView mailTemplate) throws IOException, TemplateException {
- boolean showAdditional = mailAttributes.getOtherAttributes().get("message") != null;
+ boolean showAdditional = mailAttributes.getMailType() == MailType.NEW_ACTIVE_APP && mailAttributes.getOtherAttributes().get("message") != null;
return FreeMarkerTemplateUtils.processTemplateIntoString(template, ImmutableMap.builder()
.putAll(mailTemplate.getGlobalInformation())
.put(MailTemplateElements.PORTAL_LINK, this.portalAddress == null ? "" : this.portalAddress)
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 a03794d9dc9e031a079913b66b85166756667720..b92cedea409b9577edeca2d7b850b7834deee12a 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,9 +14,11 @@ 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;
+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 +32,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 +94,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 +124,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 +132,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()
+ 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,10 +147,35 @@ 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()));
}
+ @DeleteMapping("/{id}")
+ @PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN') || hasRole('ROLE_VL_MANAGER')")
+ public ResponseEntity<Void> removeBulkDeployment(
+ @PathVariable Long id,
+ @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));
+ }
+ bulkDeploymentRepository.delete(bulk.get());
+ return ResponseEntity.ok().build();
+ }
+
+ private List<BulkDeploymentViewS> mapToViewList(List<BulkDeployment> deployments) {
@GetMapping("/refresh/{id}")
@PreAuthorize("hasRole('ROLE_SYSTEM_ADMIN') || hasRole('ROLE_VL_MANAGER')")
public ResponseEntity<BulkDeploymentViewS> getRefreshedState(@PathVariable Long id) {
@@ -159,15 +184,17 @@ public class BulkController {
private List<BulkDeploymentViewS> mapToView(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 BulkDeploymentView mapToView(BulkDeployment deployment) {
BulkDeploymentView bulkView = modelMapper.map(deployment, BulkDeploymentView.class);
bulkView.setCreator(getUserView(deployment.getCreatorId()));
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 08583400d7b96e1a1e3c44cf474202e3d4c3b378..15c439137c55ac8b47e13419f3913835f439c351 100644
--- a/src/main/java/net/geant/nmaas/portal/service/BulkApplicationService.java
+++ b/src/main/java/net/geant/nmaas/portal/service/BulkApplicationService.java
@@ -23,7 +23,9 @@ public interface BulkApplicationService {
List<BulkAppDetails> getAppsBulkDetails(BulkDeploymentView view);
- InputStreamResource getInputStreamAppBulkDetails(List<BulkAppDetails> list );
+ InputStreamResource getInputStreamAppBulkDetails(List<BulkAppDetails> list);
+
+ void deleteAppInstancesFromBulk(BulkDeploymentView bulk);
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 cb73a8fe91af9a396c5c29d6dd632deb9623a139..9f654497228a4176dce689cef1409e1522ed8dd4 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;
@@ -301,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("App instance 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"));
+ }
+
@Override
public BulkDeployment updateState(Long bulkId) {
log.info("Update all states for bulk {}", bulkId);
@@ -408,8 +428,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/main/resources/changelog.json b/src/main/resources/changelog.json
index fee877193c49c37774b1cd093bf70fd5b9d2dc7f..b46ad9eecc2904e3d08302f32f517ed8a6ec6298 100644
--- a/src/main/resources/changelog.json
+++ b/src/main/resources/changelog.json
@@ -2,7 +2,7 @@
"versions" : [
{
"verNo" : "1.6.3",
- "date" : "(2024/09/04)",
+ "date" : "(2024/09/05)",
"topic" : [
{
"title" : "New layout for the portal landing pages",
@@ -13,6 +13,16 @@
"title" : "Support for SSO accounts provisioned ahead of time",
"tags" : "[Enhancement]",
"description" : "Bulk user deployment process was enhanced with an option to indicate that given user account should allow for SSO login"
+ },
+ {
+ "title" : "New email notifications for user accounts created in bulk",
+ "tags" : "[Enhancement]",
+ "description" : "New users with accounts created in bulk process will receive customized email messages with instructions on first login"
+ },
+ {
+ "title" : "Fixed issue with selection of application version for manual upgrade",
+ "tags" : "[Bugfix]",
+ "description" : "Fix was applied to drop down version selector on manual application instance version upgrade modal"
}
]
},
diff --git a/src/test/shell/data/i18n/de.json b/src/test/shell/data/i18n/de.json
index 7c918b109d911070d0c5acac3185ae8bb8c63495..3be95453107a87a24be554ac82e93f9b52862154 100644
--- a/src/test/shell/data/i18n/de.json
+++ b/src/test/shell/data/i18n/de.json
@@ -1224,8 +1224,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 b81160208ee64ef13c35eab767ffdc226d52662a..cda3ab52fa13d53283750e4f9cdb937fb1535092 100644
--- a/src/test/shell/data/i18n/en.json
+++ b/src/test/shell/data/i18n/en.json
@@ -1227,8 +1227,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 6804efd139fea4ad1f142a9bae2d29a080f1ff10..9bfad90280fb54f451d8239f9c1c4e5d14a5fb63 100644
--- a/src/test/shell/data/i18n/fr.json
+++ b/src/test/shell/data/i18n/fr.json
@@ -1225,8 +1225,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 f96811b72a60d63ad166508d6af86b80657bcb64..4de03e0fb75ecb0b2f7b0904deedc3bb6214e708 100644
--- a/src/test/shell/data/i18n/pl.json
+++ b/src/test/shell/data/i18n/pl.json
@@ -1226,8 +1226,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" : {