diff --git a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/IssuedCertificateController.java b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/IssuedCertificateController.java index 26855e44..1c13c811 100644 --- a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/IssuedCertificateController.java +++ b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/IssuedCertificateController.java @@ -1,241 +1,241 @@ -//package hirs.attestationca.portal.page.controllers; -// -//import hirs.attestationca.persist.FilteredRecordsList; -//import hirs.attestationca.persist.entity.manager.CertificateRepository; -//import hirs.attestationca.persist.entity.manager.IssuedCertificateRepository; -//import hirs.attestationca.persist.entity.userdefined.Certificate; -//import hirs.attestationca.persist.entity.userdefined.certificate.IssuedAttestationCertificate; -//import hirs.attestationca.persist.service.CertificateService; -//import hirs.attestationca.portal.datatables.Column; -//import hirs.attestationca.portal.datatables.DataTableInput; -//import hirs.attestationca.portal.datatables.DataTableResponse; -//import hirs.attestationca.portal.page.Page; -//import hirs.attestationca.portal.page.PageController; -//import hirs.attestationca.portal.page.params.NoPageParams; -//import jakarta.servlet.http.HttpServletResponse; -//import lombok.extern.log4j.Log4j2; -//import org.apache.commons.lang3.StringUtils; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.data.domain.PageRequest; -//import org.springframework.data.domain.Pageable; -//import org.springframework.data.domain.Sort; -//import org.springframework.http.MediaType; -//import org.springframework.stereotype.Controller; -//import org.springframework.ui.Model; -//import org.springframework.util.StreamUtils; -//import org.springframework.web.bind.annotation.GetMapping; -//import org.springframework.web.bind.annotation.RequestMapping; -//import org.springframework.web.bind.annotation.RequestParam; -//import org.springframework.web.bind.annotation.ResponseBody; -//import org.springframework.web.servlet.ModelAndView; -// -//import java.io.IOException; -//import java.util.List; -//import java.util.UUID; -//import java.util.stream.Collectors; -//import java.util.zip.ZipEntry; -//import java.util.zip.ZipOutputStream; -// -//@Log4j2 -//@Controller -//@RequestMapping("/HIRS_AttestationCAPortal/portal/certificate-request/issued-certificates") -//public class IssuedCertificateController extends PageController { -// -// private final CertificateRepository certificateRepository; -// private final IssuedCertificateRepository issuedCertificateRepository; -// private final CertificateService certificateService; -// -// @Autowired -// public IssuedCertificateController( -// final CertificateRepository certificateRepository, -// final IssuedCertificateRepository issuedCertificateRepository, -// final CertificateService certificateService) { -// super(Page.TRUST_CHAIN); -// this.certificateRepository = certificateRepository; -// this.issuedCertificateRepository = issuedCertificateRepository; -// this.certificateService = certificateService; -// } -// -// /** -// * Returns the path for the view and the data model for the page. -// * -// * @param params The object to map url parameters into. -// * @param model The data model for the request. Can contain data from -// * redirect. -// * @return the path for the view and data model for the page. -// */ -// @RequestMapping -// public ModelAndView initPage( -// final NoPageParams params, final Model model) { -// return getBaseModelAndView(Page.ISSUED_CERTIFICATES); -// } -// -// @ResponseBody -// @GetMapping(value = "/list", -// produces = MediaType.APPLICATION_JSON_VALUE) -// public DataTableResponse getIssuedCertificatesTableData( -// final DataTableInput input) { -// log.debug("Handling list request for issued certificates: {}", input); -// -// // attempt to get the column property based on the order index. -// String orderColumnName = input.getOrderColumnName(); -// -// log.debug("Ordering on column: {}", orderColumnName); -// -// String searchText = input.getSearch().getValue(); -// List searchableColumns = findSearchableColumnsNames(input.getColumns()); -// -// int currentPage = input.getStart() / input.getLength(); -// Pageable pageable = PageRequest.of(currentPage, input.getLength(), Sort.by(orderColumnName)); -// -// FilteredRecordsList records = new FilteredRecordsList<>(); -// org.springframework.data.domain.Page pagedResult; -// -// if (StringUtils.isBlank(searchText)) { -// pagedResult = -// this.issuedCertificateRepository.findByArchiveFlag(false, pageable); -// } else { -// pagedResult = -// this.certificateService.findBySearchableColumnsAndArchiveFlag( -// IssuedAttestationCertificate.class, -// searchableColumns, -// searchText, -// false, pageable); -// } -// -// if (pagedResult.hasContent()) { -// records.addAll(pagedResult.getContent()); -// records.setRecordsTotal(pagedResult.getContent().size()); -// } else { -// records.setRecordsTotal(input.getLength()); -// } -// -// records.setRecordsFiltered(issuedCertificateRepository.findByArchiveFlag(false).size()); -// -// log.debug("Returning the size of the list of issued certificates: {}", records.size()); -// return new DataTableResponse<>(records, input); -// -// } -// -// /** -// * Handles request to download the cert by writing it to the response stream -// * for download. -// * -// * @param id the UUID of the cert to download -// * @param response the response object (needed to update the header with the -// * file name) -// * @throws IOException when writing to response output stream -// */ -// @GetMapping("/download") -// public void download( -// @RequestParam final String id, -// final HttpServletResponse response) -// throws IOException { -// log.info("Handling request to download {}", id); -// -// try { -// UUID uuid = UUID.fromString(id); -// Certificate certificate = certificateRepository.getCertificate(uuid); -// if (certificate == null) { -// // Use the term "record" here to avoid user confusion b/t cert and cred -// String notFoundMessage = "Unable to locate record with ID: " + uuid; -// log.warn(notFoundMessage); -// // send a 404 error when invalid certificate -// response.sendError(HttpServletResponse.SC_NOT_FOUND); -// } else { -// String fileName = "filename=\"" + getCertificateClass(certificateType).getSimpleName() -// + "_" -// + certificate.getSerialNumber() -// + ".cer\""; -// -// // Set filename for download. -// response.setHeader("Content-Disposition", "attachment;" + fileName); -// response.setContentType("application/octet-stream"); -// -// // write cert to output stream -// response.getOutputStream().write(certificate.getRawBytes()); -// } -// } catch (IllegalArgumentException ex) { -// String uuidError = "Failed to parse ID from: " + id; -// log.error(uuidError, ex); -// // send a 404 error when invalid certificate -// response.sendError(HttpServletResponse.SC_NOT_FOUND); -// } -// } -// -// /** -// * Handles request to download the certs by writing it to the response stream -// * for download in bulk. -// * -// * @param response the response object (needed to update the header with the -// * file name) -// * @throws IOException when writing to response output stream -// */ -// @GetMapping("/bulk-download") -// public void icBulkDownload(final HttpServletResponse response) -// throws IOException { -// log.info("Handling request to download all issued certificates"); -// String fileName = "issued_certificates.zip"; -// final String singleFileName = "Issued_Certificate"; -// String zipFileName; -// -// // Set filename for download. -// response.setHeader("Content-Disposition", "attachment; filename=" + fileName); -// response.setContentType("application/zip"); -// -// try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) { -// // get all files -// bulkDownload(zipOut, this.certificateRepository.findByType("IssuedAttestationCertificate"), -// singleFileName); -// // write cert to output stream -// } catch (IllegalArgumentException ex) { -// String uuidError = "Failed to parse ID from: "; -// log.error(uuidError, ex); -// // send a 404 error when invalid certificate -// response.sendError(HttpServletResponse.SC_NOT_FOUND); -// } -// } -// -// /** -// * Helper method that returns a list of column names that are searchable. -// * -// * @return searchable column names -// */ -// private List findSearchableColumnsNames(List columns) { -// -// // Retrieve all searchable columns and collect their names into a list of strings. -// return columns.stream().filter(Column::isSearchable).map(Column::getName) -// .collect(Collectors.toList()); -// } -// -// -// /** -// * Helper method that packages a collection of certificates into a zip file. -// * -// * @param zipOut zip outputs stream -// * @param certificates collection of certificates -// * @param singleFileName zip file name -// * @return zip outputs stream -// * @throws IOException if there are any issues packaging or downloading the zip file -// */ -// private ZipOutputStream bulkDownload(final ZipOutputStream zipOut, -// final List certificates, -// final String singleFileName) throws IOException { -// String zipFileName; -// // get all files -// for (Certificate certificate : certificates) { -// zipFileName = String.format("%s[%s].cer", singleFileName, -// Integer.toHexString(certificate.getCertificateHash())); -// // configure the zip entry, the properties of the 'file' -// ZipEntry zipEntry = new ZipEntry(zipFileName); -// zipEntry.setSize((long) certificate.getRawBytes().length * Byte.SIZE); -// zipEntry.setTime(System.currentTimeMillis()); -// zipOut.putNextEntry(zipEntry); -// // the content of the resource -// StreamUtils.copy(certificate.getRawBytes(), zipOut); -// zipOut.closeEntry(); -// } -// zipOut.finish(); -// return zipOut; -// } -//} +package hirs.attestationca.portal.page.controllers; + +import hirs.attestationca.persist.FilteredRecordsList; +import hirs.attestationca.persist.entity.manager.CertificateRepository; +import hirs.attestationca.persist.entity.manager.IssuedCertificateRepository; +import hirs.attestationca.persist.entity.userdefined.Certificate; +import hirs.attestationca.persist.entity.userdefined.certificate.IssuedAttestationCertificate; +import hirs.attestationca.persist.service.CertificateService; +import hirs.attestationca.portal.datatables.Column; +import hirs.attestationca.portal.datatables.DataTableInput; +import hirs.attestationca.portal.datatables.DataTableResponse; +import hirs.attestationca.portal.page.Page; +import hirs.attestationca.portal.page.PageController; +import hirs.attestationca.portal.page.params.NoPageParams; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.util.StreamUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.ModelAndView; + +import java.io.IOException; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +@Log4j2 +@Controller +@RequestMapping("/HIRS_AttestationCAPortal/portal/certificate-request/issued-certificates") +public class IssuedCertificateController extends PageController { + + private final CertificateRepository certificateRepository; + private final IssuedCertificateRepository issuedCertificateRepository; + private final CertificateService certificateService; + + @Autowired + public IssuedCertificateController( + final CertificateRepository certificateRepository, + final IssuedCertificateRepository issuedCertificateRepository, + final CertificateService certificateService) { + super(Page.TRUST_CHAIN); + this.certificateRepository = certificateRepository; + this.issuedCertificateRepository = issuedCertificateRepository; + this.certificateService = certificateService; + } + + /** + * Returns the path for the view and the data model for the page. + * + * @param params The object to map url parameters into. + * @param model The data model for the request. Can contain data from + * redirect. + * @return the path for the view and data model for the page. + */ + @RequestMapping + public ModelAndView initPage( + final NoPageParams params, final Model model) { + return getBaseModelAndView(Page.ISSUED_CERTIFICATES); + } + + @ResponseBody + @GetMapping(value = "/list", + produces = MediaType.APPLICATION_JSON_VALUE) + public DataTableResponse getIssuedCertificatesTableData( + final DataTableInput input) { + log.debug("Handling list request for issued certificates: {}", input); + + // attempt to get the column property based on the order index. + String orderColumnName = input.getOrderColumnName(); + + log.debug("Ordering on column: {}", orderColumnName); + + String searchText = input.getSearch().getValue(); + List searchableColumns = findSearchableColumnsNames(input.getColumns()); + + int currentPage = input.getStart() / input.getLength(); + Pageable pageable = PageRequest.of(currentPage, input.getLength(), Sort.by(orderColumnName)); + + FilteredRecordsList records = new FilteredRecordsList<>(); + org.springframework.data.domain.Page pagedResult; + + if (StringUtils.isBlank(searchText)) { + pagedResult = + this.issuedCertificateRepository.findByArchiveFlag(false, pageable); + } else { + pagedResult = + this.certificateService.findBySearchableColumnsAndArchiveFlag( + IssuedAttestationCertificate.class, + searchableColumns, + searchText, + false, pageable); + } + + if (pagedResult.hasContent()) { + records.addAll(pagedResult.getContent()); + records.setRecordsTotal(pagedResult.getContent().size()); + } else { + records.setRecordsTotal(input.getLength()); + } + + records.setRecordsFiltered(issuedCertificateRepository.findByArchiveFlag(false).size()); + + log.debug("Returning the size of the list of issued certificates: {}", records.size()); + return new DataTableResponse<>(records, input); + + } + + /** + * Handles request to download the cert by writing it to the response stream + * for download. + * + * @param id the UUID of the cert to download + * @param response the response object (needed to update the header with the + * file name) + * @throws IOException when writing to response output stream + */ + @GetMapping("/download") + public void download( + @RequestParam final String id, + final HttpServletResponse response) + throws IOException { + log.info("Handling request to download {}", id); + + try { + UUID uuid = UUID.fromString(id); + Certificate certificate = certificateRepository.getCertificate(uuid); + if (certificate == null) { + // Use the term "record" here to avoid user confusion b/t cert and cred + String notFoundMessage = "Unable to locate record with ID: " + uuid; + log.warn(notFoundMessage); + // send a 404 error when invalid certificate + response.sendError(HttpServletResponse.SC_NOT_FOUND); + } else { + String fileName = "filename=\"" + IssuedAttestationCertificate.class.getSimpleName() + + "_" + + certificate.getSerialNumber() + + ".cer\""; + + // Set filename for download. + response.setHeader("Content-Disposition", "attachment;" + fileName); + response.setContentType("application/octet-stream"); + + // write cert to output stream + response.getOutputStream().write(certificate.getRawBytes()); + } + } catch (IllegalArgumentException ex) { + String uuidError = "Failed to parse ID from: " + id; + log.error(uuidError, ex); + // send a 404 error when invalid certificate + response.sendError(HttpServletResponse.SC_NOT_FOUND); + } + } + + /** + * Handles request to download the certs by writing it to the response stream + * for download in bulk. + * + * @param response the response object (needed to update the header with the + * file name) + * @throws IOException when writing to response output stream + */ + @GetMapping("/bulk-download") + public void icBulkDownload(final HttpServletResponse response) + throws IOException { + log.info("Handling request to download all issued certificates"); + String fileName = "issued_certificates.zip"; + final String singleFileName = "Issued_Certificate"; + String zipFileName; + + // Set filename for download. + response.setHeader("Content-Disposition", "attachment; filename=" + fileName); + response.setContentType("application/zip"); + + try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) { + // get all files + bulkDownload(zipOut, this.certificateRepository.findByType("IssuedAttestationCertificate"), + singleFileName); + // write cert to output stream + } catch (IllegalArgumentException ex) { + String uuidError = "Failed to parse ID from: "; + log.error(uuidError, ex); + // send a 404 error when invalid certificate + response.sendError(HttpServletResponse.SC_NOT_FOUND); + } + } + + /** + * Helper method that returns a list of column names that are searchable. + * + * @return searchable column names + */ + private List findSearchableColumnsNames(List columns) { + + // Retrieve all searchable columns and collect their names into a list of strings. + return columns.stream().filter(Column::isSearchable).map(Column::getName) + .collect(Collectors.toList()); + } + + + /** + * Helper method that packages a collection of certificates into a zip file. + * + * @param zipOut zip outputs stream + * @param certificates collection of certificates + * @param singleFileName zip file name + * @return zip outputs stream + * @throws IOException if there are any issues packaging or downloading the zip file + */ + private ZipOutputStream bulkDownload(final ZipOutputStream zipOut, + final List certificates, + final String singleFileName) throws IOException { + String zipFileName; + // get all files + for (Certificate certificate : certificates) { + zipFileName = String.format("%s[%s].cer", singleFileName, + Integer.toHexString(certificate.getCertificateHash())); + // configure the zip entry, the properties of the 'file' + ZipEntry zipEntry = new ZipEntry(zipFileName); + zipEntry.setSize((long) certificate.getRawBytes().length * Byte.SIZE); + zipEntry.setTime(System.currentTimeMillis()); + zipOut.putNextEntry(zipEntry); + // the content of the resource + StreamUtils.copy(certificate.getRawBytes(), zipOut); + zipOut.closeEntry(); + } + zipOut.finish(); + return zipOut; + } +}