| 1 | package com.edtech.service; | |
| 2 | ||
| 3 | import com.edtech.model.AuditLog; | |
| 4 | import com.edtech.model.Document; | |
| 5 | import com.edtech.repository.AuditLogRepository; | |
| 6 | import com.edtech.repository.DocumentRepository; | |
| 7 | import com.edtech.repository.ProjectMemberRepository; | |
| 8 | import java.io.ByteArrayOutputStream; | |
| 9 | import java.time.format.DateTimeFormatter; | |
| 10 | import java.util.List; | |
| 11 | import java.util.Locale; | |
| 12 | import java.util.UUID; | |
| 13 | import org.openpdf.text.DocumentException; | |
| 14 | import org.openpdf.text.Font; | |
| 15 | import org.openpdf.text.FontFactory; | |
| 16 | import org.openpdf.text.PageSize; | |
| 17 | import org.openpdf.text.Paragraph; | |
| 18 | import org.openpdf.text.Phrase; | |
| 19 | import org.openpdf.text.pdf.PdfPCell; | |
| 20 | import org.openpdf.text.pdf.PdfPTable; | |
| 21 | import org.openpdf.text.pdf.PdfWriter; | |
| 22 | import org.springframework.stereotype.Service; | |
| 23 | ||
| 24 | /** Service responsavel por exportar trilhas de auditoria de documentos. */ | |
| 25 | @Service | |
| 26 | public class AuditExportService { | |
| 27 | ||
| 28 | private static final String CSV_FORMAT = "csv"; | |
| 29 | private static final String PDF_FORMAT = "pdf"; | |
| 30 | private static final String DOCUMENT_RESOURCE_TYPE = "Document"; | |
| 31 | ||
| 32 | private final AuditLogRepository auditLogRepository; | |
| 33 | private final DocumentRepository documentRepository; | |
| 34 | private final ProjectMemberRepository projectMemberRepository; | |
| 35 | private final AuditTrailCsvExporter csvExporter; | |
| 36 | ||
| 37 | /** Cria o servico com os repositorios e exportador necessarios. */ | |
| 38 | public AuditExportService( | |
| 39 | AuditLogRepository auditLogRepository, | |
| 40 | DocumentRepository documentRepository, | |
| 41 | ProjectMemberRepository projectMemberRepository, | |
| 42 | AuditTrailCsvExporter csvExporter) { | |
| 43 | this.auditLogRepository = auditLogRepository; | |
| 44 | this.documentRepository = documentRepository; | |
| 45 | this.projectMemberRepository = projectMemberRepository; | |
| 46 | this.csvExporter = csvExporter; | |
| 47 | } | |
| 48 | ||
| 49 | /** | |
| 50 | * Exporta os logs de auditoria relacionados a um documento. | |
| 51 | * | |
| 52 | * @param documentId identificador do documento. | |
| 53 | * @param userId identificador do usuario que solicitou a exportacao. | |
| 54 | * @param format formato solicitado para exportacao. | |
| 55 | * @return conteudo do arquivo exportado em bytes. | |
| 56 | */ | |
| 57 | public byte[] exportDocumentAuditTrail(UUID documentId, UUID userId, String format) { | |
| 58 | String normalizedFormat = normalizeFormat(format); | |
| 59 |
2
1. exportDocumentAuditTrail : negated conditional → KILLED 2. exportDocumentAuditTrail : negated conditional → KILLED |
if (!CSV_FORMAT.equals(normalizedFormat) && !PDF_FORMAT.equals(normalizedFormat)) { |
| 60 | throw new IllegalArgumentException("Formato invalido. Use: csv ou pdf"); | |
| 61 | } | |
| 62 | ||
| 63 | Document document = | |
| 64 | documentRepository | |
| 65 | .findById(documentId) | |
| 66 |
1
1. lambda$exportDocumentAuditTrail$0 : replaced return value with null for com/edtech/service/AuditExportService::lambda$exportDocumentAuditTrail$0 → KILLED |
.orElseThrow(() -> new RuntimeException("Document not found")); |
| 67 | ||
| 68 | projectMemberRepository | |
| 69 | .findByProjectIdAndUserId(document.getProject().getId(), userId) | |
| 70 | .orElseThrow( | |
| 71 |
1
1. lambda$exportDocumentAuditTrail$1 : replaced return value with null for com/edtech/service/AuditExportService::lambda$exportDocumentAuditTrail$1 → KILLED |
() -> new RuntimeException("Access denied: You are not a member of this project")); |
| 72 | ||
| 73 | List<AuditLog> logs = | |
| 74 | auditLogRepository.findByResourceTypeAndResourceIdOrderByCreatedAtAsc( | |
| 75 | DOCUMENT_RESOURCE_TYPE, documentId); | |
| 76 | ||
| 77 |
1
1. exportDocumentAuditTrail : negated conditional → KILLED |
if (PDF_FORMAT.equals(normalizedFormat)) { |
| 78 |
1
1. exportDocumentAuditTrail : replaced return value with null for com/edtech/service/AuditExportService::exportDocumentAuditTrail → NO_COVERAGE |
return exportPdf(logs); |
| 79 | } | |
| 80 | ||
| 81 |
1
1. exportDocumentAuditTrail : replaced return value with null for com/edtech/service/AuditExportService::exportDocumentAuditTrail → KILLED |
return csvExporter.export(logs); |
| 82 | } | |
| 83 | ||
| 84 | private byte[] exportPdf(List<AuditLog> logs) { | |
| 85 | org.openpdf.text.Document pdfDoc = new org.openpdf.text.Document(PageSize.A4.rotate()); | |
| 86 | ByteArrayOutputStream out = new ByteArrayOutputStream(); | |
| 87 | ||
| 88 | try { | |
| 89 | PdfWriter.getInstance(pdfDoc, out); | |
| 90 |
1
1. exportPdf : removed call to org/openpdf/text/Document::open → NO_COVERAGE |
pdfDoc.open(); |
| 91 | ||
| 92 | Font fontTitle = FontFactory.getFont(FontFactory.HELVETICA_BOLD); | |
| 93 |
1
1. exportPdf : removed call to org/openpdf/text/Font::setSize → NO_COVERAGE |
fontTitle.setSize(18); |
| 94 | Paragraph title = new Paragraph("Trilha de Auditoria do Documento", fontTitle); | |
| 95 |
1
1. exportPdf : removed call to org/openpdf/text/Paragraph::setAlignment → NO_COVERAGE |
title.setAlignment(Paragraph.ALIGN_CENTER); |
| 96 | pdfDoc.add(title); | |
| 97 | pdfDoc.add(new Paragraph(" ")); | |
| 98 | ||
| 99 | PdfPTable table = new PdfPTable(6); | |
| 100 |
1
1. exportPdf : removed call to org/openpdf/text/pdf/PdfPTable::setWidthPercentage → NO_COVERAGE |
table.setWidthPercentage(100f); |
| 101 |
1
1. exportPdf : removed call to org/openpdf/text/pdf/PdfPTable::setWidths → NO_COVERAGE |
table.setWidths(new float[] {1.5f, 2.5f, 2.0f, 2.0f, 1.5f, 4.0f}); |
| 102 | ||
| 103 | Font fontHeader = FontFactory.getFont(FontFactory.HELVETICA_BOLD); | |
| 104 |
1
1. exportPdf : removed call to org/openpdf/text/Font::setSize → NO_COVERAGE |
fontHeader.setSize(10); |
| 105 | String[] headers = {"ID", "Timestamp", "Ação", "Usuário ID", "IP", "Detalhes"}; | |
| 106 | for (String header : headers) { | |
| 107 | PdfPCell cell = new PdfPCell(); | |
| 108 |
1
1. exportPdf : removed call to org/openpdf/text/pdf/PdfPCell::setPhrase → NO_COVERAGE |
cell.setPhrase(new Phrase(header, fontHeader)); |
| 109 | table.addCell(cell); | |
| 110 | } | |
| 111 | ||
| 112 | Font fontData = FontFactory.getFont(FontFactory.HELVETICA); | |
| 113 |
1
1. exportPdf : removed call to org/openpdf/text/Font::setSize → NO_COVERAGE |
fontData.setSize(8); |
| 114 | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); | |
| 115 | ||
| 116 | for (AuditLog log : logs) { | |
| 117 |
1
1. exportPdf : negated conditional → NO_COVERAGE |
table.addCell(new Phrase(log.getId() != null ? log.getId().toString() : "", fontData)); |
| 118 | table.addCell( | |
| 119 | new Phrase( | |
| 120 |
1
1. exportPdf : negated conditional → NO_COVERAGE |
log.getCreatedAt() != null ? log.getCreatedAt().format(formatter) : "", fontData)); |
| 121 |
1
1. exportPdf : negated conditional → NO_COVERAGE |
table.addCell(new Phrase(log.getAction() != null ? log.getAction().name() : "", fontData)); |
| 122 | table.addCell( | |
| 123 |
1
1. exportPdf : negated conditional → NO_COVERAGE |
new Phrase(log.getUserId() != null ? log.getUserId().toString() : "", fontData)); |
| 124 |
1
1. exportPdf : negated conditional → NO_COVERAGE |
table.addCell(new Phrase(log.getIpAddress() != null ? log.getIpAddress() : "", fontData)); |
| 125 |
1
1. exportPdf : negated conditional → NO_COVERAGE |
table.addCell(new Phrase(log.getDetails() != null ? log.getDetails() : "", fontData)); |
| 126 | } | |
| 127 | ||
| 128 | pdfDoc.add(table); | |
| 129 |
1
1. exportPdf : removed call to org/openpdf/text/Document::close → NO_COVERAGE |
pdfDoc.close(); |
| 130 | ||
| 131 | } catch (DocumentException e) { | |
| 132 | throw new RuntimeException("Erro ao gerar PDF", e); | |
| 133 | } | |
| 134 | ||
| 135 |
1
1. exportPdf : replaced return value with null for com/edtech/service/AuditExportService::exportPdf → NO_COVERAGE |
return out.toByteArray(); |
| 136 | } | |
| 137 | ||
| 138 | public String buildFilename(UUID documentId, String format) { | |
| 139 |
1
1. buildFilename : replaced return value with "" for com/edtech/service/AuditExportService::buildFilename → KILLED |
return "audit-trail-" + documentId + "." + normalizeFormat(format); |
| 140 | } | |
| 141 | ||
| 142 | private String normalizeFormat(String format) { | |
| 143 |
2
1. normalizeFormat : negated conditional → KILLED 2. normalizeFormat : negated conditional → KILLED |
if (format == null || format.isBlank()) { |
| 144 |
1
1. normalizeFormat : replaced return value with "" for com/edtech/service/AuditExportService::normalizeFormat → KILLED |
return CSV_FORMAT; |
| 145 | } | |
| 146 |
1
1. normalizeFormat : replaced return value with "" for com/edtech/service/AuditExportService::normalizeFormat → KILLED |
return format.toLowerCase(Locale.ROOT); |
| 147 | } | |
| 148 | } | |
Mutations | ||
| 59 |
1.1 2.2 |
|
| 66 |
1.1 |
|
| 71 |
1.1 |
|
| 77 |
1.1 |
|
| 78 |
1.1 |
|
| 81 |
1.1 |
|
| 90 |
1.1 |
|
| 93 |
1.1 |
|
| 95 |
1.1 |
|
| 100 |
1.1 |
|
| 101 |
1.1 |
|
| 104 |
1.1 |
|
| 108 |
1.1 |
|
| 113 |
1.1 |
|
| 117 |
1.1 |
|
| 120 |
1.1 |
|
| 121 |
1.1 |
|
| 123 |
1.1 |
|
| 124 |
1.1 |
|
| 125 |
1.1 |
|
| 129 |
1.1 |
|
| 135 |
1.1 |
|
| 139 |
1.1 |
|
| 143 |
1.1 2.2 |
|
| 144 |
1.1 |
|
| 146 |
1.1 |