AuditController.java

1
package com.edtech.controller;
2
3
import com.edtech.dto.AuditLogDto;
4
import com.edtech.model.AuditLog;
5
import com.edtech.model.User;
6
import com.edtech.repository.AuditLogRepository;
7
import com.edtech.repository.UserRepository;
8
import java.time.format.DateTimeFormatter;
9
import java.util.List;
10
import java.util.stream.Collectors;
11
import org.springframework.http.ResponseEntity;
12
import org.springframework.security.access.prepost.PreAuthorize;
13
import org.springframework.web.bind.annotation.GetMapping;
14
import org.springframework.web.bind.annotation.RequestMapping;
15
import org.springframework.web.bind.annotation.RequestParam;
16
import org.springframework.web.bind.annotation.RestController;
17
18
/** Controller para buscar logs de auditoria. */
19
@RestController
20
@RequestMapping("/api/audit-logs")
21
public class AuditController {
22
23
  private final AuditLogRepository auditLogRepository;
24
  private final UserRepository userRepository;
25
26
  /**
27
   * Construtor.
28
   *
29
   * @param auditLogRepository repo
30
   * @param userRepository repo
31
   */
32
  public AuditController(AuditLogRepository auditLogRepository, UserRepository userRepository) {
33
    this.auditLogRepository = auditLogRepository;
34
    this.userRepository = userRepository;
35
  }
36
37
  /**
38
   * Busca logs de auditoria com filtro.
39
   *
40
   * @param search texto de busca
41
   * @param action acao filtrada
42
   * @return lista de logs
43
   */
44
  @GetMapping
45
  @PreAuthorize("hasRole('AUDITOR')")
46
  public ResponseEntity<List<AuditLogDto>> getAuditLogs(
47
      @RequestParam(required = false) String search,
48
      @RequestParam(required = false) String action) {
49
50
    List<AuditLog> logs = auditLogRepository.findAllByOrderByCreatedAtDesc();
51
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
52
53
    List<AuditLogDto> dtos =
54
        logs.stream()
55
            .map(
56
                log -> {
57
                  AuditLogDto dto = new AuditLogDto();
58 1 1. lambda$getAuditLogs$0 : removed call to com/edtech/dto/AuditLogDto::setId → KILLED
                  dto.setId(log.getId().toString());
59 1 1. lambda$getAuditLogs$0 : removed call to com/edtech/dto/AuditLogDto::setTimestamp → KILLED
                  dto.setTimestamp(log.getCreatedAt().format(formatter));
60 1 1. lambda$getAuditLogs$0 : removed call to com/edtech/dto/AuditLogDto::setAction → KILLED
                  dto.setAction(log.getAction().name());
61
62
                  User user = userRepository.findById(log.getUserId()).orElse(null);
63 2 1. lambda$getAuditLogs$0 : negated conditional → KILLED
2. lambda$getAuditLogs$0 : removed call to com/edtech/dto/AuditLogDto::setUserName → KILLED
                  dto.setUserName(user != null ? user.getName() : "Unknown");
64
65 1 1. lambda$getAuditLogs$0 : removed call to com/edtech/dto/AuditLogDto::setIp → KILLED
                  dto.setIp(log.getIpAddress());
66 1 1. lambda$getAuditLogs$0 : removed call to com/edtech/dto/AuditLogDto::setDetails → KILLED
                  dto.setDetails(log.getDetails());
67
68
                  // Determine Action Class and Severity based on Action
69
                  switch (log.getAction()) {
70
                    case LOGIN_SUCCESS:
71
                    case DOCUMENT_APPROVED:
72 1 1. lambda$getAuditLogs$0 : removed call to com/edtech/dto/AuditLogDto::setActionClass → KILLED
                      dto.setActionClass("green");
73 1 1. lambda$getAuditLogs$0 : removed call to com/edtech/dto/AuditLogDto::setSeverity → KILLED
                      dto.setSeverity("INFO");
74
                      break;
75
                    case LOGIN_FAILED:
76
                    case DOCUMENT_REJECTED:
77
                    case MEMBER_JOINED:
78 1 1. lambda$getAuditLogs$0 : removed call to com/edtech/dto/AuditLogDto::setActionClass → KILLED
                      dto.setActionClass("orange");
79 1 1. lambda$getAuditLogs$0 : removed call to com/edtech/dto/AuditLogDto::setSeverity → KILLED
                      dto.setSeverity("WARNING");
80
                      break;
81
                    case DELETE_DOCUMENT:
82 1 1. lambda$getAuditLogs$0 : removed call to com/edtech/dto/AuditLogDto::setActionClass → KILLED
                      dto.setActionClass("red");
83 1 1. lambda$getAuditLogs$0 : removed call to com/edtech/dto/AuditLogDto::setSeverity → KILLED
                      dto.setSeverity("CRITICAL");
84
                      break;
85
                    default:
86 1 1. lambda$getAuditLogs$0 : removed call to com/edtech/dto/AuditLogDto::setActionClass → KILLED
                      dto.setActionClass("blue");
87 1 1. lambda$getAuditLogs$0 : removed call to com/edtech/dto/AuditLogDto::setSeverity → KILLED
                      dto.setSeverity("INFO");
88
                  }
89 1 1. lambda$getAuditLogs$0 : replaced return value with null for com/edtech/controller/AuditController::lambda$getAuditLogs$0 → KILLED
                  return dto;
90
                })
91
            .collect(Collectors.toList());
92
93 2 1. getAuditLogs : negated conditional → KILLED
2. getAuditLogs : negated conditional → KILLED
    if (search != null && !search.isEmpty()) {
94
      String s = search.toLowerCase();
95
      dtos =
96
          dtos.stream()
97
              .filter(
98
                  dto ->
99 2 1. lambda$getAuditLogs$1 : replaced boolean return with true for com/edtech/controller/AuditController::lambda$getAuditLogs$1 → KILLED
2. lambda$getAuditLogs$1 : negated conditional → KILLED
                      dto.getAction().toLowerCase().contains(s)
100 1 1. lambda$getAuditLogs$1 : negated conditional → KILLED
                          || (dto.getDetails() != null
101 1 1. lambda$getAuditLogs$1 : negated conditional → KILLED
                              && dto.getDetails().toLowerCase().contains(s))
102 1 1. lambda$getAuditLogs$1 : negated conditional → KILLED
                          || dto.getUserName().toLowerCase().contains(s)
103 1 1. lambda$getAuditLogs$1 : negated conditional → KILLED
                          || dto.getIp().contains(s))
104
              .collect(Collectors.toList());
105
    }
106
107 3 1. getAuditLogs : negated conditional → KILLED
2. getAuditLogs : negated conditional → KILLED
3. getAuditLogs : negated conditional → KILLED
    if (action != null && !action.isEmpty() && !action.equals("Todas as Ações")) {
108
      dtos =
109 2 1. lambda$getAuditLogs$2 : replaced boolean return with false for com/edtech/controller/AuditController::lambda$getAuditLogs$2 → KILLED
2. lambda$getAuditLogs$2 : replaced boolean return with true for com/edtech/controller/AuditController::lambda$getAuditLogs$2 → KILLED
          dtos.stream().filter(dto -> dto.getAction().equals(action)).collect(Collectors.toList());
110
    }
111
112 1 1. getAuditLogs : replaced return value with null for com/edtech/controller/AuditController::getAuditLogs → KILLED
    return ResponseEntity.ok(dtos);
113
  }
114
115
  /**
116
   * Exporta logs de auditoria para CSV.
117
   *
118
   * @param search texto de busca
119
   * @param action acao filtrada
120
   * @return Arquivo CSV
121
   */
122
  @GetMapping("/export")
123
  @PreAuthorize("hasRole('AUDITOR')")
124
  public ResponseEntity<String> exportAuditLogs(
125
      @RequestParam(required = false) String search,
126
      @RequestParam(required = false) String action) {
127
128
    ResponseEntity<List<AuditLogDto>> response = getAuditLogs(search, action);
129
    List<AuditLogDto> dtos = response.getBody();
130
131
    StringBuilder csv = new StringBuilder();
132
    csv.append("ID,Timestamp,Action,User,IP,Details,Severity\n");
133
134 1 1. exportAuditLogs : negated conditional → KILLED
    if (dtos != null) {
135
      for (AuditLogDto dto : dtos) {
136
        csv.append(escapeCsv(dto.getId()))
137
            .append(",")
138
            .append(escapeCsv(dto.getTimestamp()))
139
            .append(",")
140
            .append(escapeCsv(dto.getAction()))
141
            .append(",")
142
            .append(escapeCsv(dto.getUserName()))
143
            .append(",")
144
            .append(escapeCsv(dto.getIp()))
145
            .append(",")
146
            .append(escapeCsv(dto.getDetails()))
147
            .append(",")
148
            .append(escapeCsv(dto.getSeverity()))
149
            .append("\n");
150
      }
151
    }
152
153
    org.springframework.http.HttpHeaders headers = new org.springframework.http.HttpHeaders();
154 1 1. exportAuditLogs : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Content-Disposition", "attachment; filename=\"audit_logs.csv\"");
155 1 1. exportAuditLogs : removed call to org/springframework/http/HttpHeaders::add → KILLED
    headers.add("Content-Type", "text/csv; charset=UTF-8");
156
157 1 1. exportAuditLogs : replaced return value with null for com/edtech/controller/AuditController::exportAuditLogs → KILLED
    return ResponseEntity.ok().headers(headers).body(csv.toString());
158
  }
159
160
  private String escapeCsv(String value) {
161 1 1. escapeCsv : negated conditional → KILLED
    if (value == null) {
162
      return "";
163
    }
164
    String escaped = value.replace("\"", "\"\"");
165 3 1. escapeCsv : negated conditional → KILLED
2. escapeCsv : negated conditional → KILLED
3. escapeCsv : negated conditional → KILLED
    if (escaped.contains(",") || escaped.contains("\"") || escaped.contains("\n")) {
166 1 1. escapeCsv : replaced return value with "" for com/edtech/controller/AuditController::escapeCsv → KILLED
      return "\"" + escaped + "\"";
167
    }
168 1 1. escapeCsv : replaced return value with "" for com/edtech/controller/AuditController::escapeCsv → KILLED
    return escaped;
169
  }
170
}

Mutations

58

1.1
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithoutFilters_ReturnsAllMappedLogs()]
removed call to com/edtech/dto/AuditLogDto::setId → KILLED

59

1.1
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithoutFilters_ReturnsAllMappedLogs()]
removed call to com/edtech/dto/AuditLogDto::setTimestamp → KILLED

60

1.1
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithSearchFilter()]
removed call to com/edtech/dto/AuditLogDto::setAction → KILLED

63

1.1
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithoutFilters_ReturnsAllMappedLogs()]
negated conditional → KILLED

2.2
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithSearchFilter()]
removed call to com/edtech/dto/AuditLogDto::setUserName → KILLED

65

1.1
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithSearchFilter()]
removed call to com/edtech/dto/AuditLogDto::setIp → KILLED

66

1.1
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithSearchFilter()]
removed call to com/edtech/dto/AuditLogDto::setDetails → KILLED

72

1.1
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithoutFilters_ReturnsAllMappedLogs()]
removed call to com/edtech/dto/AuditLogDto::setActionClass → KILLED

73

1.1
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithoutFilters_ReturnsAllMappedLogs()]
removed call to com/edtech/dto/AuditLogDto::setSeverity → KILLED

78

1.1
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithoutFilters_ReturnsAllMappedLogs()]
removed call to com/edtech/dto/AuditLogDto::setActionClass → KILLED

79

1.1
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithoutFilters_ReturnsAllMappedLogs()]
removed call to com/edtech/dto/AuditLogDto::setSeverity → KILLED

82

1.1
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithoutFilters_ReturnsAllMappedLogs()]
removed call to com/edtech/dto/AuditLogDto::setActionClass → KILLED

83

1.1
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithoutFilters_ReturnsAllMappedLogs()]
removed call to com/edtech/dto/AuditLogDto::setSeverity → KILLED

86

1.1
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithoutFilters_ReturnsAllMappedLogs()]
removed call to com/edtech/dto/AuditLogDto::setActionClass → KILLED

87

1.1
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithoutFilters_ReturnsAllMappedLogs()]
removed call to com/edtech/dto/AuditLogDto::setSeverity → KILLED

89

1.1
Location : lambda$getAuditLogs$0
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithSearchFilter()]
replaced return value with null for com/edtech/controller/AuditController::lambda$getAuditLogs$0 → KILLED

93

1.1
Location : getAuditLogs
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithSearchFilter()]
negated conditional → KILLED

2.2
Location : getAuditLogs
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithSearchFilter()]
negated conditional → KILLED

99

1.1
Location : lambda$getAuditLogs$1
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithSearchFilter()]
replaced boolean return with true for com/edtech/controller/AuditController::lambda$getAuditLogs$1 → KILLED

2.2
Location : lambda$getAuditLogs$1
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithSearchFilter()]
negated conditional → KILLED

100

1.1
Location : lambda$getAuditLogs$1
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithSearchFilter()]
negated conditional → KILLED

101

1.1
Location : lambda$getAuditLogs$1
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithSearchFilter()]
negated conditional → KILLED

102

1.1
Location : lambda$getAuditLogs$1
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithSearchFilter()]
negated conditional → KILLED

103

1.1
Location : lambda$getAuditLogs$1
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithSearchFilter()]
negated conditional → KILLED

107

1.1
Location : getAuditLogs
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithSearchFilter()]
negated conditional → KILLED

2.2
Location : getAuditLogs
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithActionFilter()]
negated conditional → KILLED

3.3
Location : getAuditLogs
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithActionFilter()]
negated conditional → KILLED

109

1.1
Location : lambda$getAuditLogs$2
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithActionFilter()]
replaced boolean return with false for com/edtech/controller/AuditController::lambda$getAuditLogs$2 → KILLED

2.2
Location : lambda$getAuditLogs$2
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithActionFilter()]
replaced boolean return with true for com/edtech/controller/AuditController::lambda$getAuditLogs$2 → KILLED

112

1.1
Location : getAuditLogs
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:getAuditLogs_WithSearchFilter()]
replaced return value with null for com/edtech/controller/AuditController::getAuditLogs → KILLED

134

1.1
Location : exportAuditLogs
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:exportAuditLogs_ReturnsCsv()]
negated conditional → KILLED

154

1.1
Location : exportAuditLogs
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:exportAuditLogs_ReturnsCsv()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

155

1.1
Location : exportAuditLogs
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:exportAuditLogs_ReturnsCsv()]
removed call to org/springframework/http/HttpHeaders::add → KILLED

157

1.1
Location : exportAuditLogs
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:exportAuditLogs_ReturnsCsv()]
replaced return value with null for com/edtech/controller/AuditController::exportAuditLogs → KILLED

161

1.1
Location : escapeCsv
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:exportAuditLogs_ReturnsCsv()]
negated conditional → KILLED

165

1.1
Location : escapeCsv
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:exportAuditLogs_ReturnsCsv()]
negated conditional → KILLED

2.2
Location : escapeCsv
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:exportAuditLogs_ReturnsCsv()]
negated conditional → KILLED

3.3
Location : escapeCsv
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:exportAuditLogs_ReturnsCsv()]
negated conditional → KILLED

166

1.1
Location : escapeCsv
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:exportAuditLogs_ReturnsCsv()]
replaced return value with "" for com/edtech/controller/AuditController::escapeCsv → KILLED

168

1.1
Location : escapeCsv
Killed by : com.edtech.controller.AuditControllerTest.[engine:junit-jupiter]/[class:com.edtech.controller.AuditControllerTest]/[method:exportAuditLogs_ReturnsCsv()]
replaced return value with "" for com/edtech/controller/AuditController::escapeCsv → KILLED

Active mutators

Tests examined


Report generated by PIT 1.16.1