AuditTrailCsvExporter.java

1
package com.edtech.service;
2
3
import com.edtech.model.AuditLog;
4
import java.io.ByteArrayOutputStream;
5
import java.io.OutputStreamWriter;
6
import java.nio.charset.StandardCharsets;
7
import java.util.List;
8
import org.springframework.stereotype.Component;
9
10
/** Transforma logs de auditoria em arquivos CSV. */
11
@Component
12
public class AuditTrailCsvExporter {
13
14
  /**
15
   * Gera um CSV em memoria com os principais dados da trilha de auditoria.
16
   *
17
   * @param logs logs que devem ser exportados.
18
   * @return conteudo do arquivo CSV em bytes.
19
   */
20
  public byte[] export(List<AuditLog> logs) {
21
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
22
23
    try (OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8)) {
24
25 1 1. export : removed call to com/edtech/service/AuditTrailCsvExporter::writeRow → KILLED
      writeRow(
26
          writer,
27
          "data_hora",
28
          "usuario_id",
29
          "acao",
30
          "tipo_recurso",
31
          "id_recurso",
32
          "ip",
33
          "detalhes");
34
35
      for (AuditLog log : logs) {
36 1 1. export : removed call to com/edtech/service/AuditTrailCsvExporter::writeRow → KILLED
        writeRow(
37
            writer,
38 1 1. export : negated conditional → SURVIVED
            log.getCreatedAt() != null ? log.getCreatedAt().toString() : "",
39 1 1. export : negated conditional → KILLED
            log.getUserId() != null ? log.getUserId().toString() : "",
40 1 1. export : negated conditional → KILLED
            log.getAction() != null ? log.getAction().name() : "",
41 1 1. export : negated conditional → SURVIVED
            log.getResourceType() != null ? log.getResourceType() : "",
42 1 1. export : negated conditional → KILLED
            log.getResourceId() != null ? log.getResourceId().toString() : "",
43 1 1. export : negated conditional → SURVIVED
            log.getIpAddress() != null ? log.getIpAddress() : "",
44 1 1. export : negated conditional → KILLED
            log.getDetails() != null ? log.getDetails() : "");
45
      }
46
47 1 1. export : removed call to java/io/OutputStreamWriter::flush → KILLED
      writer.flush();
48 1 1. export : replaced return value with null for com/edtech/service/AuditTrailCsvExporter::export → KILLED
      return outputStream.toByteArray();
49
    } catch (Exception e) {
50
      throw new RuntimeException("Falha ao gerar CSV da trilha de auditoria", e);
51
    }
52
  }
53
54
  private void writeRow(OutputStreamWriter writer, String... values) throws java.io.IOException {
55 2 1. writeRow : negated conditional → KILLED
2. writeRow : changed conditional boundary → KILLED
    for (int index = 0; index < values.length; index++) {
56 2 1. writeRow : negated conditional → KILLED
2. writeRow : changed conditional boundary → KILLED
      if (index > 0) {
57 1 1. writeRow : removed call to java/io/OutputStreamWriter::write → KILLED
        writer.write(",");
58
      }
59 1 1. writeRow : removed call to java/io/OutputStreamWriter::write → KILLED
      writer.write(escape(values[index]));
60
    }
61 1 1. writeRow : removed call to java/io/OutputStreamWriter::write → KILLED
    writer.write("\r\n");
62
  }
63
64
  private String escape(String value) {
65 1 1. escape : negated conditional → KILLED
    String safeValue = value != null ? value : "";
66
    // Prevent CSV formula injection (CWE-1236)
67 1 1. escape : negated conditional → KILLED
    if (!safeValue.isEmpty()) {
68
      char first = safeValue.charAt(0);
69 6 1. escape : negated conditional → KILLED
2. escape : negated conditional → KILLED
3. escape : negated conditional → KILLED
4. escape : negated conditional → KILLED
5. escape : negated conditional → KILLED
6. escape : negated conditional → KILLED
      if (first == '=' || first == '+' || first == '-' || first == '@'
70
          || first == '\t' || first == '\r') {
71
        safeValue = "'" + safeValue;
72
      }
73
    }
74 1 1. escape : negated conditional → KILLED
    if (safeValue.contains("\"")
75 1 1. escape : negated conditional → KILLED
        || safeValue.contains(",")
76 1 1. escape : negated conditional → KILLED
        || safeValue.contains("\n")
77 1 1. escape : negated conditional → KILLED
        || safeValue.contains("\r")) {
78 1 1. escape : replaced return value with "" for com/edtech/service/AuditTrailCsvExporter::escape → KILLED
      return "\"" + safeValue.replace("\"", "\"\"") + "\"";
79
    }
80 1 1. escape : replaced return value with "" for com/edtech/service/AuditTrailCsvExporter::escape → KILLED
    return safeValue;
81
  }
82
}

Mutations

25

1.1
Location : export
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:exportEscapesCsvSpecialCharacters()]
removed call to com/edtech/service/AuditTrailCsvExporter::writeRow → KILLED

36

1.1
Location : export
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithNullFields_ShouldHandleGracefully()]
removed call to com/edtech/service/AuditTrailCsvExporter::writeRow → KILLED

38

1.1
Location : export
Killed by : none
negated conditional → SURVIVED
Covering tests

39

1.1
Location : export
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithNullFields_ShouldHandleGracefully()]
negated conditional → KILLED

40

1.1
Location : export
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithNullFields_ShouldHandleGracefully()]
negated conditional → KILLED

41

1.1
Location : export
Killed by : none
negated conditional → SURVIVED
Covering tests

42

1.1
Location : export
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithNullFields_ShouldHandleGracefully()]
negated conditional → KILLED

43

1.1
Location : export
Killed by : none
negated conditional → SURVIVED
Covering tests

44

1.1
Location : export
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithCarriageReturn_ShouldEscape()]
negated conditional → KILLED

47

1.1
Location : export
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithNullFields_ShouldHandleGracefully()]
removed call to java/io/OutputStreamWriter::flush → KILLED

48

1.1
Location : export
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithNullFields_ShouldHandleGracefully()]
replaced return value with null for com/edtech/service/AuditTrailCsvExporter::export → KILLED

55

1.1
Location : writeRow
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithNullFields_ShouldHandleGracefully()]
negated conditional → KILLED

2.2
Location : writeRow
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithNullFields_ShouldHandleGracefully()]
changed conditional boundary → KILLED

56

1.1
Location : writeRow
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithNullFields_ShouldHandleGracefully()]
negated conditional → KILLED

2.2
Location : writeRow
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:exportEscapesCsvSpecialCharacters()]
changed conditional boundary → KILLED

57

1.1
Location : writeRow
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithNullFields_ShouldHandleGracefully()]
removed call to java/io/OutputStreamWriter::write → KILLED

59

1.1
Location : writeRow
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithCarriageReturn_ShouldEscape()]
removed call to java/io/OutputStreamWriter::write → KILLED

61

1.1
Location : writeRow
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:exportEscapesCsvSpecialCharacters()]
removed call to java/io/OutputStreamWriter::write → KILLED

65

1.1
Location : escape
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithCarriageReturn_ShouldEscape()]
negated conditional → KILLED

67

1.1
Location : escape
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithNullFields_ShouldHandleGracefully()]
negated conditional → KILLED

69

1.1
Location : escape
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithCarriageReturn_ShouldEscape()]
negated conditional → KILLED

2.2
Location : escape
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithCarriageReturn_ShouldEscape()]
negated conditional → KILLED

3.3
Location : escape
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithCarriageReturn_ShouldEscape()]
negated conditional → KILLED

4.4
Location : escape
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithCarriageReturn_ShouldEscape()]
negated conditional → KILLED

5.5
Location : escape
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithCarriageReturn_ShouldEscape()]
negated conditional → KILLED

6.6
Location : escape
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithCarriageReturn_ShouldEscape()]
negated conditional → KILLED

74

1.1
Location : escape
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithNullFields_ShouldHandleGracefully()]
negated conditional → KILLED

75

1.1
Location : escape
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithNullFields_ShouldHandleGracefully()]
negated conditional → KILLED

76

1.1
Location : escape
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithNullFields_ShouldHandleGracefully()]
negated conditional → KILLED

77

1.1
Location : escape
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithNullFields_ShouldHandleGracefully()]
negated conditional → KILLED

78

1.1
Location : escape
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:export_WithCarriageReturn_ShouldEscape()]
replaced return value with "" for com/edtech/service/AuditTrailCsvExporter::escape → KILLED

80

1.1
Location : escape
Killed by : com.edtech.service.AuditTrailCsvExporterTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditTrailCsvExporterTest]/[method:exportEscapesCsvSpecialCharacters()]
replaced return value with "" for com/edtech/service/AuditTrailCsvExporter::escape → KILLED

Active mutators

Tests examined


Report generated by PIT 1.25.9 support