AuditLogService.java

1
package com.edtech.service;
2
3
import com.edtech.model.AuditAction;
4
import com.edtech.model.AuditLog;
5
import com.edtech.repository.AuditLogRepository;
6
import jakarta.servlet.http.HttpServletRequest;
7
import java.util.UUID;
8
import org.slf4j.Logger;
9
import org.slf4j.LoggerFactory;
10
import org.springframework.stereotype.Service;
11
import org.springframework.web.context.request.RequestContextHolder;
12
import org.springframework.web.context.request.ServletRequestAttributes;
13
14
/** Servico responsavel por registrar logs de auditoria no sistema. */
15
@Service
16
public class AuditLogService {
17
  private static final String DOCUMENT_RESOURCE_TYPE = "Document";
18
  private static final Logger log = LoggerFactory.getLogger(AuditLogService.class);
19
  private final AuditLogRepository auditLogRepository;
20
21
  /**
22
   * Construtor para injecao de dependencias.
23
   *
24
   * @param auditLogRepository Repositorio de logs de auditoria.
25
   */
26
  public AuditLogService(AuditLogRepository auditLogRepository) {
27
    this.auditLogRepository = auditLogRepository;
28
  }
29
30
  private String getClientIp() {
31
    try {
32
      ServletRequestAttributes attributes =
33
          (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
34 1 1. getClientIp : negated conditional → KILLED
      if (attributes != null) {
35
        HttpServletRequest request = attributes.getRequest();
36
        String forwardedFor = request.getHeader("X-Forwarded-For");
37 2 1. getClientIp : negated conditional → KILLED
2. getClientIp : negated conditional → KILLED
        if (forwardedFor != null && !forwardedFor.isEmpty()) {
38 1 1. getClientIp : replaced return value with "" for com/edtech/service/AuditLogService::getClientIp → KILLED
          return forwardedFor.split(",")[0].trim();
39
        }
40 1 1. getClientIp : replaced return value with "" for com/edtech/service/AuditLogService::getClientIp → KILLED
        return request.getRemoteAddr();
41
      }
42
    } catch (Exception ignored) {
43
      log.debug("Erro ao extrair o IP do cliente", ignored);
44
    }
45 1 1. getClientIp : replaced return value with "" for com/edtech/service/AuditLogService::getClientIp → KILLED
    return "UNKNOWN";
46
  }
47
48
  /**
49
   * Registra uma acao de auditoria detalhada.
50
   *
51
   * @param action Acao realizada.
52
   * @param userId ID do usuario.
53
   * @param resourceType Tipo do recurso.
54
   * @param resourceId ID do recurso.
55
   * @param ip IP do cliente.
56
   * @param details Detalhes adicionais.
57
   * @return Log de auditoria salvo.
58
   */
59
  public AuditLog log(
60
      AuditAction action,
61
      UUID userId,
62
      String resourceType,
63
      UUID resourceId,
64
      String ip,
65
      String details) {
66
    UUID institutionId = resolveInstitutionId();
67 1 1. log : replaced return value with null for com/edtech/service/AuditLogService::log → KILLED
    return log(action, userId, resourceType, resourceId, ip, details, institutionId);
68
  }
69
70
  /** Javadoc. */
71
  public AuditLog log(
72
      AuditAction action,
73
      UUID userId,
74
      String resourceType,
75
      UUID resourceId,
76
      String ip,
77
      String details,
78
      UUID institutionId) {
79
    try {
80 1 1. log : negated conditional → KILLED
      String clientIp = ip != null ? ip : getClientIp();
81
      AuditLog auditLog =
82
          new AuditLog(
83
              institutionId,
84
              userId,
85
              action,
86
              resourceType,
87
              resourceId,
88
              clientIp,
89
              details);
90 1 1. log : replaced return value with null for com/edtech/service/AuditLogService::log → KILLED
      return auditLogRepository.save(auditLog);
91
    } catch (Exception e) {
92
      log.error("Erro em salvar o log da auditoria: {}", e.getMessage(), e);
93
      return null;
94
    }
95
  }
96
97
  private UUID resolveInstitutionId() {
98
    try {
99
      org.springframework.security.core.Authentication auth =
100
          org.springframework.security.core.context.SecurityContextHolder.getContext()
101
              .getAuthentication();
102 2 1. resolveInstitutionId : negated conditional → NO_COVERAGE
2. resolveInstitutionId : negated conditional → SURVIVED
      if (auth != null && auth.getPrincipal() instanceof com.edtech.model.User user) {
103 1 1. resolveInstitutionId : replaced return value with null for com/edtech/service/AuditLogService::resolveInstitutionId → NO_COVERAGE
        return user.getInstitutionId();
104
      }
105
    } catch (Exception e) {
106
      log.debug("Could not resolve institutionId from security context", e);
107
    }
108 1 1. resolveInstitutionId : replaced return value with null for com/edtech/service/AuditLogService::resolveInstitutionId → SURVIVED
    return java.util.UUID.fromString("00000000-0000-0000-0000-000000000001");
109
  }
110
111
  /**
112
   * Registra uma acao de auditoria simples, sem vinculo direto com um recurso especifico.
113
   *
114
   * @param userId ID do usuario.
115
   * @param action Acao realizada.
116
   * @param details Detalhes adicionais.
117
   * @return Log de auditoria salvo.
118
   */
119
  public AuditLog logAction(UUID userId, AuditAction action, String details) {
120 1 1. logAction : replaced return value with null for com/edtech/service/AuditLogService::logAction → KILLED
    return log(action, userId, null, null, null, details);
121
  }
122
123
  /**
124
   * Registra uma acao de auditoria relacionada a um documento especifico.
125
   *
126
   * @param userId ID do usuario que executou a acao.
127
   * @param action Acao realizada.
128
   * @param documentId ID do documento afetado.
129
   * @param details Detalhes adicionais da acao.
130
   * @return Log de auditoria salvo.
131
   */
132
  public AuditLog logDocumentAction(
133
      UUID userId, AuditAction action, UUID documentId, String details) {
134 1 1. logDocumentAction : replaced return value with null for com/edtech/service/AuditLogService::logDocumentAction → NO_COVERAGE
    return log(action, userId, DOCUMENT_RESOURCE_TYPE, documentId, null, details);
135
  }
136
}
137

Mutations

34

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

37

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

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

38

1.1
Location : getClientIp
Killed by : com.edtech.service.AuditLogServiceTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditLogServiceTest]/[method:testLog_WithXForwardedFor()]
replaced return value with "" for com/edtech/service/AuditLogService::getClientIp → KILLED

40

1.1
Location : getClientIp
Killed by : com.edtech.service.AuditLogServiceTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditLogServiceTest]/[method:testLog_WithRequestContextIp()]
replaced return value with "" for com/edtech/service/AuditLogService::getClientIp → KILLED

45

1.1
Location : getClientIp
Killed by : com.edtech.service.AuditLogServiceTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditLogServiceTest]/[method:testLog_WithoutContextFallbackToUnknown()]
replaced return value with "" for com/edtech/service/AuditLogService::getClientIp → KILLED

67

1.1
Location : log
Killed by : com.edtech.service.AuditLogServiceTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditLogServiceTest]/[method:testLog_WithExplicitIp()]
replaced return value with null for com/edtech/service/AuditLogService::log → KILLED

80

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

90

1.1
Location : log
Killed by : com.edtech.service.AuditLogServiceTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditLogServiceTest]/[method:testLog_WithExplicitIp()]
replaced return value with null for com/edtech/service/AuditLogService::log → KILLED

102

1.1
Location : resolveInstitutionId
Killed by : none
negated conditional → NO_COVERAGE

2.2
Location : resolveInstitutionId
Killed by : none
negated conditional → SURVIVED
Covering tests

103

1.1
Location : resolveInstitutionId
Killed by : none
replaced return value with null for com/edtech/service/AuditLogService::resolveInstitutionId → NO_COVERAGE

108

1.1
Location : resolveInstitutionId
Killed by : none
replaced return value with null for com/edtech/service/AuditLogService::resolveInstitutionId → SURVIVED
Covering tests

120

1.1
Location : logAction
Killed by : com.edtech.service.AuditLogServiceTest.[engine:junit-jupiter]/[class:com.edtech.service.AuditLogServiceTest]/[method:testLog_WithoutContextFallbackToUnknown()]
replaced return value with null for com/edtech/service/AuditLogService::logAction → KILLED

134

1.1
Location : logDocumentAction
Killed by : none
replaced return value with null for com/edtech/service/AuditLogService::logDocumentAction → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.25.9 support