v3_issue_811: Can now do global search on all certificates, devices, rims, and pcr values. The table doesnt accuratle refelect how many items have been filtered, validation summaries still need work for the global search feature to work, need to also work on searching on just on indiviudal columns.
Some checks are pending
Dotnet Provisioner Unit Tests / Restore and Run Unit Tests (ubuntu-latest) (push) Waiting to run
Dotnet Provisioner Unit Tests / Restore and Run Unit Tests (windows-2022) (push) Waiting to run
Dotnet Provisioner Unit Tests / Evaluate Tests (push) Blocked by required conditions
HIRS Build and Unit Test / ACA_Provisioner_Unit_Tests (push) Waiting to run
HIRS System Tests / DockerTests (push) Waiting to run

This commit is contained in:
ThatSilentCoder 2025-04-15 15:50:56 -04:00
parent f7ee7d3d88
commit 70e130c8e8
9 changed files with 392 additions and 204 deletions

View File

@ -69,7 +69,7 @@ public class CertificateService {
* certificates whose field values matches the provided search term.
*
* @param entityClass generic entity class
* @param searchableColumns list of the searchable column name
* @param searchableColumns list of the searchable column names
* @param searchText text that was input in the search textbox
* @param archiveFlag archive flag
* @param pageable pageable
@ -77,14 +77,14 @@ public class CertificateService {
* @return page full of the generic certificates.
*/
public <T extends Certificate> Page<T> findCertificatesBySearchableColumnsAndArchiveFlag(
Class<T> entityClass,
final Class<T> entityClass,
final List<String> searchableColumns,
final String searchText,
Boolean archiveFlag,
Pageable pageable) {
final boolean archiveFlag,
final Pageable pageable) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<T> query = criteriaBuilder.createQuery(entityClass);
Root<T> certificate = query.from(entityClass);
Root<T> rootCertificate = query.from(entityClass);
List<Predicate> predicates = new ArrayList<>();
@ -102,7 +102,7 @@ public class CertificateService {
}
Predicate predicate =
criteriaBuilder.like(criteriaBuilder.lower(certificate.get(columnName)),
criteriaBuilder.like(criteriaBuilder.lower(rootCertificate.get(columnName)),
"%" + searchText.toLowerCase() + "%");
predicates.add(predicate);
}
@ -112,7 +112,7 @@ public class CertificateService {
// Add archiveFlag condition if specified
query.where(criteriaBuilder.and(likeConditions,
criteriaBuilder.equal(certificate.get("archiveFlag"), archiveFlag)));
criteriaBuilder.equal(rootCertificate.get("archiveFlag"), archiveFlag)));
// Apply pagination
TypedQuery<T> typedQuery = entityManager.createQuery(query);
@ -131,7 +131,7 @@ public class CertificateService {
* @param uuid certificate uuid
* @return certificate
*/
public Certificate findCertificate(UUID uuid) {
public Certificate findCertificate(final UUID uuid) {
return this.certificateRepository.getCertificate(uuid);
}
@ -303,7 +303,7 @@ public class CertificateService {
}
/**
* Helper method that packages a collection of certificates into a zip file.
* Packages a collection of certificates into a zip file.
*
* @param zipOut zip outputs streams
* @param singleFileName zip file name

View File

@ -0,0 +1,95 @@
package hirs.attestationca.persist.service;
import hirs.attestationca.persist.entity.userdefined.rim.ReferenceDigestValue;
import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
*
*/
@Service
@Log4j2
public class ReferenceDigestValueService {
private final EntityManager entityManager;
public ReferenceDigestValueService(EntityManager entityManager) {
this.entityManager = entityManager;
}
/**
* @param searchableColumns list of the searchable column name
* @param searchText text that was input in the search textbox
* @param pageable pageable
* @return page full of reference digest values
*/
public Page<ReferenceDigestValue> findReferenceDigestValuesBySearchableColumns(
final List<String> searchableColumns,
final String searchText,
final Pageable pageable) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<ReferenceDigestValue> query =
criteriaBuilder.createQuery(ReferenceDigestValue.class);
Root<ReferenceDigestValue> referenceDigestValueRoot =
query.from(ReferenceDigestValue.class);
List<Predicate> predicates = new ArrayList<>();
// Dynamically add search conditions for each field that should be searchable
if (!StringUtils.isBlank(searchText)) {
// Dynamically loop through columns and create LIKE conditions for each searchable column
for (String columnName : searchableColumns) {
// Get the attribute type from entity root
Path<?> fieldPath = referenceDigestValueRoot.get(columnName);
// if the field is a string type
if (String.class.equals(fieldPath.getJavaType())) {
Predicate predicate =
criteriaBuilder.like(
criteriaBuilder.lower(referenceDigestValueRoot.get(columnName)),
"%" + searchText.toLowerCase() + "%");
predicates.add(predicate);
}
// if the field is a non-string type
else {
Expression<String> fieldAsString = criteriaBuilder
.literal(fieldPath).as(String.class);
Predicate predicate = criteriaBuilder.like(
criteriaBuilder.lower(fieldAsString),
"%" + searchText.toLowerCase() + "%"
);
predicates.add(predicate);
}
}
}
query.where(criteriaBuilder.or(predicates.toArray(new Predicate[0])));
// Apply pagination
TypedQuery<ReferenceDigestValue> typedQuery = entityManager.createQuery(query);
int totalRows = typedQuery.getResultList().size(); // Get the total count for pagination
typedQuery.setFirstResult((int) pageable.getOffset());
typedQuery.setMaxResults(pageable.getPageSize());
// Wrap the result in a Page object to return pagination info
List<ReferenceDigestValue> resultList = typedQuery.getResultList();
return new PageImpl<>(resultList, pageable, totalRows);
}
}

View File

@ -1,6 +1,10 @@
package hirs.attestationca.persist.service;
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
import hirs.attestationca.persist.entity.userdefined.ReferenceManifest;
import hirs.attestationca.persist.entity.userdefined.rim.BaseReferenceManifest;
import hirs.attestationca.persist.entity.userdefined.rim.SupportReferenceManifest;
import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder;
@ -13,9 +17,14 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
*
@ -25,15 +34,33 @@ import java.util.List;
public class ReferenceManifestService {
private final EntityManager entityManager;
private final ReferenceManifestRepository referenceManifestRepository;
private final ReferenceDigestValueRepository referenceDigestValueRepository;
public ReferenceManifestService(EntityManager entityManager) {
public ReferenceManifestService(EntityManager entityManager,
ReferenceManifestRepository referenceManifestRepository,
ReferenceDigestValueRepository referenceDigestValueRepository) {
this.entityManager = entityManager;
this.referenceManifestRepository = referenceManifestRepository;
this.referenceDigestValueRepository = referenceDigestValueRepository;
}
public Page<ReferenceManifest> findRIMBySearchableColumns(final List<String> searchableColumns,
final String searchText,
final Pageable pageable) {
/**
* Takes the provided column names, the search term that the user entered and attempts to find
* RIMS whose field values matches the provided search term.
*
* @param searchableColumns list of the searchable column names
* @param searchText text that was input in the search textbox
* @param archiveFlag archive flag
* @param pageable pageable
* @return page full of reference manifests
*/
public Page<ReferenceManifest> findRIMSBySearchableColumnsAndArchiveFlag(
final List<String> searchableColumns,
final String searchText,
final boolean archiveFlag,
final Pageable pageable) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<ReferenceManifest> query = criteriaBuilder.createQuery(ReferenceManifest.class);
Root<ReferenceManifest> rimRoot = query.from(ReferenceManifest.class);
@ -62,7 +89,11 @@ public class ReferenceManifestService {
}
}
query.where(criteriaBuilder.or(predicates.toArray(new Predicate[0])));
Predicate likeConditions = criteriaBuilder.or(predicates.toArray(new Predicate[0]));
// Add archiveFlag condition if specified
query.where(criteriaBuilder.and(likeConditions,
criteriaBuilder.equal(rimRoot.get("archiveFlag"), archiveFlag)));
// Apply pagination
TypedQuery<ReferenceManifest> typedQuery = entityManager.createQuery(query);
@ -74,4 +105,79 @@ public class ReferenceManifestService {
List<ReferenceManifest> resultList = typedQuery.getResultList();
return new PageImpl<>(resultList, pageable, totalRows);
}
/**
* Retrieves all RIMs from the database based on the provided archive flag.
*
* @param archiveFlag archive flag
* @param pageable pageable
* @return page of RIMs
*/
public Page<ReferenceManifest> findAllRIMsByArchiveFlag(final boolean archiveFlag,
final Pageable pageable) {
return referenceManifestRepository.findByArchiveFlag(archiveFlag, pageable);
}
/**
* This method takes the parameter and looks for this information in the
* Database.
*
* @param uuid RIM uuid
* @return the associated RIM from the DB
*/
public ReferenceManifest findSpecifiedRIM(final UUID uuid) {
if (referenceManifestRepository.existsById(uuid)) {
return referenceManifestRepository.getReferenceById(uuid);
}
return null;
}
/**
* Packages a collection of RIMs into a zip file.
*
* @param zipOut zip outputs streams
* @throws IOException if there are any issues packaging or downloading the zip file
*/
public void bulkDownloadRIMS(ZipOutputStream zipOut) throws IOException {
List<ReferenceManifest> allRIMs = this.referenceManifestRepository.findAll();
List<ReferenceManifest> referenceManifestList = new ArrayList<>();
for (ReferenceManifest rim : allRIMs) {
if ((rim instanceof BaseReferenceManifest)
|| (rim instanceof SupportReferenceManifest)) {
referenceManifestList.add(rim);
}
}
String zipFileName;
// get all files
for (ReferenceManifest rim : referenceManifestList) {
if (rim.getFileName().isEmpty()) {
zipFileName = "";
} else {
// configure the zip entry, the properties of the 'file'
zipFileName = rim.getFileName();
}
ZipEntry zipEntry = new ZipEntry(zipFileName);
zipEntry.setSize((long) rim.getRimBytes().length * Byte.SIZE);
zipEntry.setTime(System.currentTimeMillis());
zipOut.putNextEntry(zipEntry);
// the content of the resource
StreamUtils.copy(rim.getRimBytes(), zipOut);
zipOut.closeEntry();
}
zipOut.finish();
}
/**
* Deletes the specified reference manifest.
*
* @param referencedManifest
*/
public void deleteSpecifiedRIM(ReferenceManifest referencedManifest) {
referenceManifestRepository.delete(referencedManifest);
}
}

View File

@ -39,10 +39,12 @@ public class DevicePageController extends PageController<NoPageParams> {
/**
* Device Page Controller constructor.
*
* @param deviceService device service
*/
@Autowired
public DevicePageController(
DeviceService deviceService) {
final DeviceService deviceService) {
super(Page.DEVICES);
this.deviceService = deviceService;
}
@ -66,7 +68,7 @@ public class DevicePageController extends PageController<NoPageParams> {
* information that will be displayed on the devices page.
*
* @param input data table input.
* @return a data table response
* @return data table of devices
*/
@ResponseBody
@GetMapping(value = "/list",
@ -109,6 +111,7 @@ public class DevicePageController extends PageController<NoPageParams> {
FilteredRecordsList<HashMap<String, Object>> records
= this.deviceService.retrieveDevicesAndAssociatedCertificates(deviceList);
log.info("Returning the size of the list of devices: {}", records.size());
return new DataTableResponse<>(records, input);
}

View File

@ -263,7 +263,7 @@ public class PlatformCredentialPageController extends PageController<NoPageParam
* @throws URISyntaxException if malformed URI
*/
@PostMapping("/upload")
protected RedirectView upload(
protected RedirectView uploadPlatformCredentials(
@RequestParam("file") final MultipartFile[] files,
final RedirectAttributes attr) throws URISyntaxException {

View File

@ -1,6 +1,5 @@
package hirs.attestationca.portal.page.controllers;
import hirs.attestationca.persist.DBManagerException;
import hirs.attestationca.persist.FilteredRecordsList;
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
@ -18,10 +17,12 @@ import hirs.attestationca.portal.page.PageMessages;
import hirs.attestationca.portal.page.params.NoPageParams;
import hirs.utils.tpm.eventlog.TCGEventLog;
import hirs.utils.tpm.eventlog.TpmPcrEvent;
import jakarta.persistence.EntityNotFoundException;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import jakarta.xml.bind.UnmarshalException;
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;
@ -29,7 +30,6 @@ 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.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@ -54,7 +54,6 @@ import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
@ -76,12 +75,13 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
*
* @param referenceManifestRepository the reference manifest manager
* @param referenceDigestValueRepository this is the reference event manager
* @param referenceManifestService reference manifest service
*/
@Autowired
public ReferenceManifestPageController(
final ReferenceManifestRepository referenceManifestRepository,
final ReferenceDigestValueRepository referenceDigestValueRepository,
ReferenceManifestService referenceManifestService) {
final ReferenceManifestService referenceManifestService) {
super(Page.REFERENCE_MANIFESTS);
this.referenceManifestRepository = referenceManifestRepository;
this.referenceDigestValueRepository = referenceDigestValueRepository;
@ -103,21 +103,19 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
}
/**
* Returns the list of RIMs using the data table input for paging, ordering,
* and filtering.
* Processes request to retrieve the collection of RIMs that will be displayed on the RIM page.
*
* @param input the data tables input
* @return the data tables response, including the result set and paging
* information
* @param input data table input
* @return data table of RIMs
*/
@ResponseBody
@GetMapping(value = "/list",
produces = MediaType.APPLICATION_JSON_VALUE)
public DataTableResponse<ReferenceManifest> getTableData(
public DataTableResponse<ReferenceManifest> getRIMTableData(
@Valid final DataTableInput input) {
log.info("Received request to display list of reference manifests");
log.debug("Request received a datatable input object for the reference manifest page " +
" page: {}", input);
log.debug("Request received a datatable input object for the reference manifest page "
+ " page: {}", input);
String orderColumnName = input.getOrderColumnName();
log.debug("Ordering on column: {}", orderColumnName);
@ -127,9 +125,19 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
FilteredRecordsList<ReferenceManifest> records = new FilteredRecordsList<>();
int currentPage = input.getStart() / input.getLength();
Pageable paging = PageRequest.of(currentPage, input.getLength(), Sort.by(orderColumnName));
org.springframework.data.domain.Page<ReferenceManifest> pagedResult =
referenceManifestRepository.findByArchiveFlag(false, paging);
Pageable pageable = PageRequest.of(currentPage, input.getLength(), Sort.by(orderColumnName));
org.springframework.data.domain.Page<ReferenceManifest> pagedResult;
if (StringUtils.isBlank(searchText)) {
pagedResult = this.referenceManifestService.findAllRIMsByArchiveFlag(false, pageable);
} else {
pagedResult =
this.referenceManifestService.findRIMSBySearchableColumnsAndArchiveFlag(searchableColumns
, searchText,
false,
pageable);
}
int rimCount = 0;
if (pagedResult.hasContent()) {
@ -144,12 +152,12 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
records.setRecordsFiltered(referenceManifestRepository.findByArchiveFlag(false).size());
log.debug("Returning list of size: {}", records.size());
log.info("Returning the size of the list of reference manifests: {}", records.size());
return new DataTableResponse<>(records, input);
}
/**
* Upload and processes a reference manifest(s).
* Processes request to upload one or more reference manifest(s) to the ACA.
*
* @param files the files to process
* @param attr the redirection attributes
@ -158,7 +166,7 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
* @throws Exception if malformed URI
*/
@PostMapping("/upload")
protected RedirectView upload(
protected RedirectView uploadRIMs(
@RequestParam("file") final MultipartFile[] files,
final RedirectAttributes attr) throws URISyntaxException, Exception {
Map<String, Object> model = new HashMap<>();
@ -197,6 +205,7 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
log.info("Storing swidtag {}", rim.getFileName());
this.referenceManifestRepository.save(rim);
});
supportRims.forEach((rim) -> {
log.info("Storing event log {}", rim.getFileName());
this.referenceManifestRepository.save(rim);
@ -212,7 +221,7 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
// pass in the updated support rims
// and either update or add the events
processTpmEvents(new ArrayList<SupportReferenceManifest>(updatedSupportRims.values()));
processTpmEvents(new ArrayList<>(updatedSupportRims.values()));
//Add messages to the model
model.put(MESSAGES_ATTRIBUTE, messages);
@ -222,7 +231,84 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
}
/**
* Archives (soft delete) the Reference Integrity Manifest entry.
* Processes request to download the RIM by writing it to the response stream
* for download.
*
* @param id the UUID of the rim to download
* @param response the response object (needed to update the header with the
* file name)
* @throws java.io.IOException when writing to response output stream
*/
@GetMapping("/download")
public void downloadSingleRIM(@RequestParam final String id,
final HttpServletResponse response)
throws IOException {
log.info("Received request to download RIM id {}", id);
try {
UUID uuid = UUID.fromString(id);
ReferenceManifest referenceManifest = this.referenceManifestService.findSpecifiedRIM(uuid);
if (referenceManifest == null) {
final String notFoundMessage = "Unable to locate RIM with ID: " + uuid;
log.warn(notFoundMessage);
throw new EntityNotFoundException(notFoundMessage);
}
// Set filename for download.
response.setHeader("Content-Disposition",
"attachment;" + "filename=\"" + referenceManifest.getFileName()
);
response.setContentType("application/octet-stream");
// write cert to output stream
response.getOutputStream().write(referenceManifest.getRimBytes());
} catch (Exception ex) {
log.error("An exception was thrown while attempting to download the"
+ " specified RIM", ex);
// send a 404 error when an exception is thrown while attempting to download the
// specified RIM
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
/**
* Processes request to bulk download RIMs 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 bulkDownloadRIMs(final HttpServletResponse response)
throws IOException {
log.info("Handling request to download all Reference Integrity Manifests");
String fileName = "rims.zip";
// Set filename for download.
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
response.setContentType("application/zip");
try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
this.referenceManifestService.bulkDownloadRIMS(zipOut);
// write cert to output stream
} catch (Exception exception) {
log.error("An exception was thrown while attempting to bulk download all the"
+ "reference integrity manifests", exception);
// send a 404 error when an exception is thrown while attempting to download the
// reference manifests
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
/**
* Processes request to archive/soft delete the provided Reference Integrity Manifest.
*
* @param id the UUID of the rim to delete
* @param attr RedirectAttributes used to forward data back to the original
@ -233,151 +319,39 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
@PostMapping("/delete")
public RedirectView delete(@RequestParam final String id,
final RedirectAttributes attr) throws URISyntaxException {
log.info("Handling request to delete {}", id);
log.info("Received request to delete RIM id {}", id);
Map<String, Object> model = new HashMap<>();
PageMessages messages = new PageMessages();
try {
ReferenceManifest referenceManifest = getRimFromDb(id);
UUID uuid = UUID.fromString(id);
ReferenceManifest referenceManifest = this.referenceManifestService.findSpecifiedRIM(uuid);
if (referenceManifest == null) {
String notFoundMessage = "Unable to locate RIM with ID: " + id;
String notFoundMessage = "Unable to locate RIM to delete with ID: " + id;
messages.addErrorMessage(notFoundMessage);
log.warn(notFoundMessage);
} else {
referenceManifestRepository.delete(referenceManifest);
String deleteCompletedMessage = "RIM successfully deleted";
messages.addInfoMessage(deleteCompletedMessage);
log.info(deleteCompletedMessage);
throw new EntityNotFoundException(notFoundMessage);
}
} catch (IllegalArgumentException iaEx) {
String uuidError = "Failed to parse ID from: " + id;
messages.addErrorMessage(uuidError);
log.error(uuidError, iaEx);
} catch (DBManagerException dbmEx) {
String dbError = "Failed to archive cert: " + id;
messages.addErrorMessage(dbError);
log.error(dbError, dbmEx);
this.referenceManifestService.deleteSpecifiedRIM(referenceManifest);
String deleteCompletedMessage = "RIM successfully deleted";
messages.addInfoMessage(deleteCompletedMessage);
log.info(deleteCompletedMessage);
} catch (Exception exception) {
final String errorMessage = "An exception was thrown while attempting to download the"
+ " specified RIM";
messages.addErrorMessage(errorMessage);
log.error(errorMessage, exception);
}
model.put(MESSAGES_ATTRIBUTE, messages);
return redirectTo(Page.REFERENCE_MANIFESTS, new NoPageParams(), model, attr);
}
/**
* Handles request to download the rim by writing it to the response stream
* for download.
*
* @param id the UUID of the rim to download
* @param response the response object (needed to update the header with the
* file name)
* @throws java.io.IOException when writing to response output stream
*/
@GetMapping("/download")
public void download(@RequestParam final String id,
final HttpServletResponse response)
throws IOException {
log.info("Handling RIM request to download {}", id);
try {
ReferenceManifest referenceManifest = getRimFromDb(id);
if (referenceManifest == null) {
String notFoundMessage = "Unable to locate RIM with ID: " + id;
log.warn(notFoundMessage);
// send a 404 error when invalid Reference Manifest
response.sendError(HttpServletResponse.SC_NOT_FOUND);
} else {
// Set filename for download.
response.setHeader("Content-Disposition",
"attachment;" + "filename=\"" + referenceManifest.getFileName()
// Set filename for download.
);
response.setContentType("application/octet-stream");
// write cert to output stream
response.getOutputStream().write(referenceManifest.getRimBytes());
}
} 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 bulk of RIMs 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 java.io.IOException when writing to response output stream
*/
@GetMapping("/bulk")
public void bulk(final HttpServletResponse response)
throws IOException {
log.info("Handling request to download all Reference Integrity Manifests");
String fileName = "rims.zip";
String zipFileName;
// Set filename for download.
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
response.setContentType("application/zip");
List<ReferenceManifest> referenceManifestList = new LinkedList<>();
for (ReferenceManifest rim : referenceManifestRepository.findAll()) {
if ((rim instanceof BaseReferenceManifest)
|| (rim instanceof SupportReferenceManifest)) {
referenceManifestList.add(rim);
}
}
try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
// get all files
for (ReferenceManifest rim : referenceManifestList) {
if (rim.getFileName().isEmpty()) {
zipFileName = "";
} else {
// configure the zip entry, the properties of the 'file'
zipFileName = rim.getFileName();
}
ZipEntry zipEntry = new ZipEntry(zipFileName);
zipEntry.setSize((long) rim.getRimBytes().length * Byte.SIZE);
zipEntry.setTime(System.currentTimeMillis());
zipOut.putNextEntry(zipEntry);
// the content of the resource
StreamUtils.copy(rim.getRimBytes(), zipOut);
zipOut.closeEntry();
}
zipOut.finish();
// 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);
}
}
/**
* This method takes the parameter and looks for this information in the
* Database.
*
* @param id of the RIM
* @return the associated RIM from the DB
* @throws IllegalArgumentException
*/
private ReferenceManifest getRimFromDb(final String id) throws IllegalArgumentException {
UUID uuid = UUID.fromString(id);
if (referenceManifestRepository.existsById(uuid)) {
return referenceManifestRepository.getReferenceById(uuid);
} else {
return null;
}
}
/**
* Takes the rim files provided and returns a {@link ReferenceManifest}
@ -455,7 +429,6 @@ public class ReferenceManifestPageController extends PageController<NoPageParams
.collect(Collectors.toList());
}
private Map<String, SupportReferenceManifest> updateSupportRimInfo(
final List<SupportReferenceManifest> dbSupportRims) {
SupportReferenceManifest supportRim;

View File

@ -1,25 +1,21 @@
package hirs.attestationca.portal.page.controllers;
import hirs.attestationca.persist.CriteriaModifier;
import hirs.attestationca.persist.DBManagerException;
import hirs.attestationca.persist.FilteredRecordsList;
import hirs.attestationca.persist.entity.manager.ReferenceDigestValueRepository;
import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
import hirs.attestationca.persist.entity.userdefined.Certificate;
import hirs.attestationca.persist.entity.userdefined.rim.ReferenceDigestValue;
import hirs.attestationca.persist.entity.userdefined.rim.SupportReferenceManifest;
import hirs.attestationca.persist.service.ReferenceDigestValueService;
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.persistence.EntityManager;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;
import jakarta.validation.Valid;
import lombok.extern.log4j.Log4j2;
import org.hibernate.Session;
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;
@ -32,7 +28,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import java.lang.ref.Reference;
import java.util.List;
import java.util.stream.Collectors;
/**
* Controller for the TPM Events page.
@ -44,8 +41,7 @@ public class RimDatabasePageController extends PageController<NoPageParams> {
private final ReferenceDigestValueRepository referenceDigestValueRepository;
private final ReferenceManifestRepository referenceManifestRepository;
@Autowired(required = false)
private EntityManager entityManager;
private final ReferenceDigestValueService referenceDigestValueService;
/**
* Constructor providing the Page's display and routing specification.
@ -55,10 +51,12 @@ public class RimDatabasePageController extends PageController<NoPageParams> {
*/
@Autowired
public RimDatabasePageController(final ReferenceDigestValueRepository referenceDigestValueRepository,
final ReferenceManifestRepository referenceManifestRepository) {
final ReferenceManifestRepository referenceManifestRepository,
ReferenceDigestValueService referenceDigestValueService) {
super(Page.RIM_DATABASE);
this.referenceDigestValueRepository = referenceDigestValueRepository;
this.referenceManifestRepository = referenceManifestRepository;
this.referenceDigestValueService = referenceDigestValueService;
}
/**
@ -76,8 +74,8 @@ public class RimDatabasePageController extends PageController<NoPageParams> {
}
/**
* Returns the list of TPM Events using the data table input for paging, ordering,
* and filtering.
* Processes request to retrieve the collection of TPM Events that will be displayed
* on the rim database page.
*
* @param input the data tables input
* @return the data tables response, including the result set and paging
@ -88,31 +86,30 @@ public class RimDatabasePageController extends PageController<NoPageParams> {
produces = MediaType.APPLICATION_JSON_VALUE)
public DataTableResponse<ReferenceDigestValue> getTableData(
@Valid final DataTableInput input) {
log.info("Handling request for summary list: {}", input);
log.info("Received request to display list of TPM events");
log.debug("Request received a datatable input object for the RIM database page: {}", input);
String orderColumnName = input.getOrderColumnName();
log.info("Ordering on column: {}", orderColumnName);
log.debug("Ordering on column: {}", orderColumnName);
// check that the alert is not archived and that it is in the specified report
CriteriaModifier criteriaModifier = new CriteriaModifier() {
@Override
public void modify(final CriteriaQuery criteriaQuery) {
Session session = entityManager.unwrap(Session.class);
CriteriaBuilder cb = session.getCriteriaBuilder();
Root<ReferenceDigestValue> rimRoot = criteriaQuery.from(Reference.class);
criteriaQuery.select(rimRoot).distinct(true)
.where(cb.isNull(rimRoot.get(Certificate.ARCHIVE_FIELD)));
}
};
log.info("Querying with the following dataTableInput: {}", input);
final String searchText = input.getSearch().getValue();
final List<String> searchableColumns = findSearchableColumnsNames(input.getColumns());
FilteredRecordsList<ReferenceDigestValue> referenceDigestValues = new FilteredRecordsList<>();
int currentPage = input.getStart() / input.getLength();
Pageable paging = PageRequest.of(currentPage, input.getLength(), Sort.by(orderColumnName));
org.springframework.data.domain.Page<ReferenceDigestValue> pagedResult =
referenceDigestValueRepository.findAll(paging);
Pageable pageable = PageRequest.of(currentPage, input.getLength(), Sort.by(orderColumnName));
org.springframework.data.domain.Page<ReferenceDigestValue> pagedResult;
if (StringUtils.isBlank(searchText)) {
pagedResult =
this.referenceDigestValueRepository.findAll(pageable);
} else {
pagedResult =
this.referenceDigestValueService.findReferenceDigestValuesBySearchableColumns(
searchableColumns,
searchText, pageable);
}
if (pagedResult.hasContent()) {
referenceDigestValues.addAll(pagedResult.getContent());
@ -120,6 +117,7 @@ public class RimDatabasePageController extends PageController<NoPageParams> {
} else {
referenceDigestValues.setRecordsTotal(input.getLength());
}
referenceDigestValues.setRecordsFiltered(referenceDigestValueRepository.count());
// might be able to get rid of this, maybe right a query that looks for not updated
@ -138,7 +136,20 @@ public class RimDatabasePageController extends PageController<NoPageParams> {
}
}
log.debug("Returning list of size: {}", referenceDigestValues.size());
log.info("Returning the size of the list of TPM events: {}", referenceDigestValues.size());
return new DataTableResponse<>(referenceDigestValues, input);
}
/**
* Helper method that returns a list of column names that are searchable.
*
* @param columns columns
* @return searchable column names
*/
private List<String> findSearchableColumnsNames(final List<Column> 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());
}
}

View File

@ -1,4 +1,4 @@
<!-- <%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%-- JSP TAGS --%>
<%@taglib prefix="c" uri="jakarta.tags.core" %>
@ -6,7 +6,7 @@
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@taglib prefix="my" tagdir="/WEB-INF/tags"%>
<%-- CONTENT --%> -->
<%-- CONTENT --%>
<my:page>
<jsp:attribute name="script">
<script

View File

@ -1,4 +1,4 @@
<!-- <%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%-- JSP TAGS --%>
<%@taglib prefix="c" uri="jakarta.tags.core" %>
@ -6,7 +6,7 @@
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@taglib prefix="my" tagdir="/WEB-INF/tags"%>
<%-- CONTENT --%> -->
<%-- CONTENT --%>
<my:page>
<jsp:attribute name="script">
<script