| 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 |
|
| 59 |
1.1 |
|
| 60 |
1.1 |
|
| 63 |
1.1 2.2 |
|
| 65 |
1.1 |
|
| 66 |
1.1 |
|
| 72 |
1.1 |
|
| 73 |
1.1 |
|
| 78 |
1.1 |
|
| 79 |
1.1 |
|
| 82 |
1.1 |
|
| 83 |
1.1 |
|
| 86 |
1.1 |
|
| 87 |
1.1 |
|
| 89 |
1.1 |
|
| 93 |
1.1 2.2 |
|
| 99 |
1.1 2.2 |
|
| 100 |
1.1 |
|
| 101 |
1.1 |
|
| 102 |
1.1 |
|
| 103 |
1.1 |
|
| 107 |
1.1 2.2 3.3 |
|
| 109 |
1.1 2.2 |
|
| 112 |
1.1 |
|
| 134 |
1.1 |
|
| 154 |
1.1 |
|
| 155 |
1.1 |
|
| 157 |
1.1 |
|
| 161 |
1.1 |
|
| 165 |
1.1 2.2 3.3 |
|
| 166 |
1.1 |
|
| 168 |
1.1 |