diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java index e81a872b8..e4d4112b1 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java @@ -1,12 +1,14 @@ package edu.internet2.tier.shibboleth.admin.ui.controller; import edu.internet2.tier.shibboleth.admin.ui.domain.shib.properties.ShibPropertySet; +import edu.internet2.tier.shibboleth.admin.ui.domain.shib.properties.ShibPropertySetting; import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; import edu.internet2.tier.shibboleth.admin.ui.service.ShibConfigurationService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tags; +import org.apache.tomcat.util.http.fileupload.IOUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -21,6 +23,15 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + @RestController @RequestMapping(value = "/api/shib") @Tags(value = {@Tag(name = "Shibboleth Properties")}) @@ -47,7 +58,7 @@ public ResponseEntity getAllPropertySets() { return ResponseEntity.ok(service.getAllPropertySets()); } - @GetMapping("/property/set/{resourceId}") + @GetMapping(value="/property/set/{resourceId}", produces="applcation/json") @Transactional(readOnly = true) @Operation(description = "Return the property set with the given resourceId", summary = "Return the property set with the given resourceId", method = "GET") @@ -55,6 +66,50 @@ public ResponseEntity getPropertySet(@PathVariable Integer resourceId) throws return ResponseEntity.ok(service.getSet(resourceId)); } + @GetMapping(value="/property/set/{resourceId}", produces="application/zip") + @Transactional(readOnly = true) + @Operation(description = "Return the property set with the given resourceId as a zip file of the properties files", + summary = "Return the property set with the given resourceId as a zip file of the properties files", method = "GET") + public ResponseEntity getPropertySetAsZip(@PathVariable Integer resourceId) throws EntityNotFoundException, IOException { + ShibPropertySet set = service.getSet(resourceId); + StringBuilder sb = new StringBuilder("attachment; filename=\"").append(set.getName()).append(".zip\""); + return ResponseEntity.ok().header("Content-Disposition", sb.toString()).body(prepDownloadAsZip(convertPropertiesToMaps(set.getProperties()))); + } + + private Map> convertPropertiesToMaps(List properties) { + HashMap> result = new HashMap<>(); + for (ShibPropertySetting setting:properties){ + String confFile = setting.getConfigFile(); + if (!result.containsKey(confFile)) { + Map props = new HashMap<>(); + result.put(confFile,props); + } + Map props = result.get(confFile); + props.put(setting.getPropertyName(), setting.getPropertyValue()); +// result.put(confFile,props); + } + return result; + } + + private byte[] prepDownloadAsZip(Map> propertiesFiles) throws IOException { + ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(); + ZipOutputStream zipOutputStream = new ZipOutputStream(byteOutputStream); + + for (String filename : propertiesFiles.keySet()) { + zipOutputStream.putNextEntry(new ZipEntry(filename)); + Map properties = propertiesFiles.get(filename); + StringBuilder props = new StringBuilder(); + for (String key : properties.keySet()) { + props.append(key).append("=").append(properties.get(key)).append("\n"); + } + ByteArrayInputStream inputStream = new ByteArrayInputStream(props.toString().getBytes()); + IOUtils.copy(inputStream, zipOutputStream); + zipOutputStream.closeEntry(); + } + zipOutputStream.close(); + return byteOutputStream.toByteArray(); + } + @DeleteMapping("/property/set/{resourceId}") @Secured("ROLE_ADMIN") @Transactional diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerExceptionHandler.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerExceptionHandler.java index bc16bb739..cbc9cb133 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerExceptionHandler.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerExceptionHandler.java @@ -10,13 +10,20 @@ import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +import java.io.IOException; + @ControllerAdvice(assignableTypes = {ShibPropertiesController.class}) public class ShibPropertiesControllerExceptionHandler extends ResponseEntityExceptionHandler { @ExceptionHandler({ EntityNotFoundException.class }) public ResponseEntity handleEntityNotFoundException(EntityNotFoundException e, WebRequest request) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse(HttpStatus.NOT_FOUND, e.getMessage())); } - + + @ExceptionHandler({ IOException.class }) + public ResponseEntity handleIOException(EntityNotFoundException e, WebRequest request) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error creating file"); + } + @ExceptionHandler({ ObjectIdExistsException.class }) public ResponseEntity handleObjectIdExistsException(ObjectIdExistsException e, WebRequest request) { HttpHeaders headers = new HttpHeaders();