Skip to content

Commit d056602

Browse files
committed
feat: enhance UtmIncident resource with auditing support and improved alert validation
1 parent 5fb970d commit d056602

File tree

2 files changed

+90
-131
lines changed

2 files changed

+90
-131
lines changed

backend/src/main/java/com/park/utmstack/service/incident/UtmIncidentService.java

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.park.utmstack.service.dto.incident.NewIncidentDTO;
1818
import com.park.utmstack.service.dto.incident.RelatedIncidentAlertsDTO;
1919
import com.park.utmstack.service.incident.util.ResolveIncidentStatus;
20+
import com.park.utmstack.util.exceptions.IncidentAlertConflictException;
2021
import org.slf4j.Logger;
2122
import org.slf4j.LoggerFactory;
2223
import org.springframework.data.domain.Page;
@@ -27,10 +28,7 @@
2728
import org.springframework.util.CollectionUtils;
2829

2930
import javax.validation.Valid;
30-
import java.util.Arrays;
31-
import java.util.Date;
32-
import java.util.List;
33-
import java.util.Optional;
31+
import java.util.*;
3432
import java.util.stream.Collectors;
3533

3634
/**
@@ -76,7 +74,6 @@ public UtmIncidentService(UtmIncidentRepository utmIncidentRepository,
7674
*/
7775
public UtmIncident save(UtmIncident utmIncident) {
7876
final String ctx = ".save";
79-
log.debug("Request to save UtmIncident : {}", utmIncident);
8077
try {
8178
return utmIncidentRepository.save(utmIncident);
8279
} catch (Exception e) {
@@ -140,6 +137,8 @@ public UtmIncident changeStatus(UtmIncident utmIncident) {
140137
public UtmIncident createIncident(NewIncidentDTO newIncidentDTO) {
141138
final String ctx = CLASSNAME + ".createIncident";
142139
try {
140+
validateAlertsNotAlreadyLinked(newIncidentDTO.getAlertList(), ctx);
141+
143142
UtmIncident utmIncident = new UtmIncident();
144143
utmIncident.setIncidentName(newIncidentDTO.getIncidentName());
145144
utmIncident.setIncidentDescription(newIncidentDTO.getIncidentDescription());
@@ -177,10 +176,25 @@ public UtmIncident addAlertsIncident(@Valid AddToIncidentDTO addToIncidentDTO) {
177176
final String ctx = CLASSNAME + ".addAlertsIncident";
178177
try {
179178
log.debug("Request to add alert to UtmIncident : {}", addToIncidentDTO);
179+
180+
List<RelatedIncidentAlertsDTO> alertIds = addToIncidentDTO.getAlertList();
181+
182+
String alertsIds = alertIds.stream().map(RelatedIncidentAlertsDTO::getAlertId).collect(Collectors.joining(","));
183+
Map<String, Object> extra = Map.of(
184+
"alertIds", alertsIds,
185+
"source", "service"
186+
);
187+
String attemptMsg = String.format("Attempt to add %d alerts to incident %d", addToIncidentDTO.getAlertList().size(), addToIncidentDTO.getIncidentId());
188+
eventService.createEvent(attemptMsg, ApplicationEventType.INCIDENT_ALERT_ADD_ATTEMPT, extra);
189+
190+
validateAlertsNotAlreadyLinked(addToIncidentDTO.getAlertList(), ctx);
180191
UtmIncident utmIncident = utmIncidentRepository.findById(addToIncidentDTO.getIncidentId()).orElseThrow(() -> new RuntimeException(ctx + ": Incident not found"));
181192
saveRelatedAlerts(addToIncidentDTO.getAlertList(), utmIncident.getId());
182193
String historyMessage = String.format("New %d alerts added to incident", addToIncidentDTO.getAlertList().size());
183194
utmIncidentHistoryService.createHistory(IncidentHistoryActionEnum.INCIDENT_ALERT_ADD, utmIncident.getId(), "New alerts added to incident", historyMessage);
195+
196+
eventService.createEvent(historyMessage, ApplicationEventType.INCIDENT_ALERTS_ADDED, extra);
197+
184198
return utmIncident;
185199
} catch (Exception e) {
186200
String msg = ctx + ": " + e.getMessage();
@@ -284,4 +298,20 @@ private void sendIncidentsEmail(List<String> alertIds, UtmIncident utmIncident)
284298
eventService.createEvent(msg, ApplicationEventType.ERROR);
285299
}
286300
}
301+
302+
private void validateAlertsNotAlreadyLinked(List<RelatedIncidentAlertsDTO> alertList, String ctx) {
303+
304+
List<String> alertIds = alertList.stream()
305+
.map(RelatedIncidentAlertsDTO::getAlertId)
306+
.collect(Collectors.toList());
307+
308+
List<String> alertsFound = utmIncidentAlertService.existsAnyAlert(alertIds);
309+
310+
if (!alertsFound.isEmpty()) {
311+
String alertIdsList = String.join(", ", alertIds);
312+
String msg = "Some alerts are already linked to another incident. Alert IDs: " + alertIdsList + ". Check the related incidents for more details.";
313+
314+
throw new IncidentAlertConflictException(ctx + ": " + msg);
315+
}
316+
}
287317
}

backend/src/main/java/com/park/utmstack/web/rest/incident/UtmIncidentResource.java

Lines changed: 55 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -2,60 +2,44 @@
22

33
import com.park.utmstack.domain.application_events.enums.ApplicationEventType;
44
import com.park.utmstack.domain.incident.UtmIncident;
5-
import com.park.utmstack.service.application_events.ApplicationEventService;
65
import com.park.utmstack.service.dto.incident.*;
7-
import com.park.utmstack.service.incident.UtmIncidentAlertService;
86
import com.park.utmstack.service.incident.UtmIncidentQueryService;
97
import com.park.utmstack.service.incident.UtmIncidentService;
10-
import com.park.utmstack.util.UtilResponse;
8+
import com.park.utmstack.util.exceptions.NoAlertsProvidedException;
119
import com.park.utmstack.web.rest.errors.BadRequestAlertException;
1210
import com.park.utmstack.web.rest.util.HeaderUtil;
1311
import com.park.utmstack.web.rest.util.PaginationUtil;
14-
import org.slf4j.Logger;
15-
import org.slf4j.LoggerFactory;
12+
import lombok.RequiredArgsConstructor;
13+
import lombok.extern.slf4j.Slf4j;
1614
import org.springframework.data.domain.Page;
1715
import org.springframework.data.domain.Pageable;
1816
import org.springframework.http.HttpHeaders;
19-
import org.springframework.http.HttpStatus;
2017
import org.springframework.http.ResponseEntity;
2118
import org.springframework.util.CollectionUtils;
2219
import org.springframework.web.bind.annotation.*;
23-
import tech.jhipster.web.util.ResponseUtil;
20+
import com.park.utmstack.aop.logging.AuditEvent;
2421

2522
import javax.validation.Valid;
2623
import java.net.URI;
2724
import java.net.URISyntaxException;
2825
import java.util.List;
2926
import java.util.Optional;
30-
import java.util.stream.Collectors;
3127

3228
/**
3329
* REST controller for managing UtmIncident.
3430
*/
3531
@RestController
32+
@RequiredArgsConstructor
33+
@Slf4j
3634
@RequestMapping("/api")
3735
public class UtmIncidentResource {
38-
private final String CLASS_NAME = "UtmIncidentResource";
39-
private final Logger log = LoggerFactory.getLogger(UtmIncidentResource.class);
4036

4137
private static final String ENTITY_NAME = "utmIncident";
4238

4339
private final UtmIncidentService utmIncidentService;
4440

45-
private final UtmIncidentAlertService utmIncidentAlertService;
46-
4741
private final UtmIncidentQueryService utmIncidentQueryService;
48-
private final ApplicationEventService applicationEventService;
49-
50-
public UtmIncidentResource(UtmIncidentService utmIncidentService,
51-
UtmIncidentAlertService utmIncidentAlertService,
52-
UtmIncidentQueryService utmIncidentQueryService,
53-
ApplicationEventService applicationEventService) {
54-
this.utmIncidentService = utmIncidentService;
55-
this.utmIncidentAlertService = utmIncidentAlertService;
56-
this.utmIncidentQueryService = utmIncidentQueryService;
57-
this.applicationEventService = applicationEventService;
58-
}
42+
5943

6044
/**
6145
* Creates a new incident based on the provided details.
@@ -75,38 +59,21 @@ public UtmIncidentResource(UtmIncidentService utmIncidentService,
7559
* @throws IllegalArgumentException if the input data is invalid.
7660
*/
7761
@PostMapping("/utm-incidents")
62+
@AuditEvent(
63+
attemptType = ApplicationEventType.INCIDENT_CREATION_ATTEMPT,
64+
attemptMessage = "Attempt to create a new incident initiated",
65+
successType = ApplicationEventType.INCIDENT_CREATION_SUCCESS,
66+
successMessage = "Incident created successfully"
67+
)
7868
public ResponseEntity<UtmIncident> createUtmIncident(@Valid @RequestBody NewIncidentDTO newIncidentDTO) {
7969
final String ctx = ".createUtmIncident";
80-
try {
81-
if (CollectionUtils.isEmpty(newIncidentDTO.getAlertList())) {
82-
String msg = ctx + ": A new incident has to have at least one alert related";
83-
log.error(msg);
84-
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);
85-
return UtilResponse.buildErrorResponse(HttpStatus.BAD_REQUEST, msg);
86-
}
87-
88-
List<String> alertIds = newIncidentDTO.getAlertList().stream()
89-
.map(RelatedIncidentAlertsDTO::getAlertId)
90-
.collect(Collectors.toList());
91-
92-
List<String> alertsFound = utmIncidentAlertService.existsAnyAlert(alertIds);
93-
94-
if (!alertsFound.isEmpty()) {
95-
String alertIdsList = String.join(", ", alertIds);
96-
String msg = "Some alerts are already linked to another incident. Alert IDs: " + alertIdsList + ". Check the related incidents for more details.";
97-
log.error(msg);
98-
applicationEventService.createEvent(ctx + ": " + msg , ApplicationEventType.ERROR);
99-
return UtilResponse.buildErrorResponse(HttpStatus.CONFLICT, utmIncidentAlertService.formatAlertMessage(alertsFound));
100-
}
101-
102-
103-
return ResponseEntity.ok(utmIncidentService.createIncident(newIncidentDTO));
104-
} catch (Exception e) {
105-
String msg = ctx + ": " + e.getMessage();
106-
log.error(msg);
107-
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);
108-
return UtilResponse.buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, msg);
70+
71+
if (CollectionUtils.isEmpty(newIncidentDTO.getAlertList())) {
72+
String msg = ctx + ": A new incident has to have at least one alert related";
73+
throw new NoAlertsProvidedException(ctx + ": " + msg);
10974
}
75+
76+
return ResponseEntity.ok(utmIncidentService.createIncident(newIncidentDTO));
11077
}
11178

11279
/**
@@ -124,36 +91,22 @@ public ResponseEntity<UtmIncident> createUtmIncident(@Valid @RequestBody NewInci
12491
* @throws URISyntaxException if the Location URI syntax is incorrect
12592
*/
12693
@PostMapping("/utm-incidents/add-alerts")
94+
@AuditEvent(
95+
attemptType = ApplicationEventType.INCIDENT_ALERT_ADD_ATTEMPT,
96+
attemptMessage = "Attempt to add alerts to incident initiated",
97+
successType = ApplicationEventType.INCIDENT_ALERT_ADD_SUCCESS,
98+
successMessage = "Alerts added to incident successfully"
99+
)
127100
public ResponseEntity<UtmIncident> addAlertsToUtmIncident(@Valid @RequestBody AddToIncidentDTO addToIncidentDTO) throws URISyntaxException {
128-
final String ctx = ".addAlertsToUtmIncident";
129-
try {
130-
log.debug("REST request to save UtmIncident : {}", addToIncidentDTO);
131-
if (CollectionUtils.isEmpty(addToIncidentDTO.getAlertList())) {
132-
throw new BadRequestAlertException("Add utmIncident cannot already have an empty related alerts", ENTITY_NAME, "alertList");
133-
}
134-
List<String> alertIds = addToIncidentDTO.getAlertList().stream()
135-
.map(RelatedIncidentAlertsDTO::getAlertId)
136-
.collect(Collectors.toList());
137-
138-
List<String> alertsFound = utmIncidentAlertService.existsAnyAlert(alertIds);
139-
140-
if (!alertsFound.isEmpty()) {
141-
String alertIdsList = String.join(", ", alertIds);
142-
String msg = "Some alerts are already linked to another incident. Alert IDs: " + alertIdsList + ". Check the related incidents for more details.";
143-
log.error(msg);
144-
applicationEventService.createEvent(ctx + ": " + msg , ApplicationEventType.ERROR);
145-
return UtilResponse.buildErrorResponse(HttpStatus.CONFLICT, utmIncidentAlertService.formatAlertMessage(alertsFound));
146-
}
147-
UtmIncident result = utmIncidentService.addAlertsIncident(addToIncidentDTO);
148-
return ResponseEntity.created(new URI("/api/utm-incidents/add-alerts" + result.getId()))
101+
102+
if (CollectionUtils.isEmpty(addToIncidentDTO.getAlertList())) {
103+
throw new NoAlertsProvidedException("Add utmIncident cannot already have an empty related alerts");
104+
}
105+
106+
UtmIncident result = utmIncidentService.addAlertsIncident(addToIncidentDTO);
107+
return ResponseEntity.created(new URI("/api/utm-incidents/add-alerts" + result.getId()))
149108
.headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
150109
.body(result);
151-
} catch (Exception e) {
152-
String msg = ctx + ": " + e.getMessage();
153-
log.error(msg);
154-
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);
155-
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(HeaderUtil.createFailureAlert(CLASS_NAME, null, msg)).body(null);
156-
}
157110
}
158111

159112
/**
@@ -166,23 +119,22 @@ public ResponseEntity<UtmIncident> addAlertsToUtmIncident(@Valid @RequestBody Ad
166119
* @throws URISyntaxException if the Location URI syntax is incorrect
167120
*/
168121
@PutMapping("/utm-incidents/change-status")
169-
public ResponseEntity<UtmIncident> updateUtmIncident(@Valid @RequestBody UtmIncident utmIncident) throws URISyntaxException {
170-
final String ctx = ".updateUtmIncident";
171-
try {
172-
log.debug("REST request to update UtmIncident : {}", utmIncident);
173-
if (utmIncident.getId() == null) {
174-
throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull");
175-
}
176-
UtmIncident result = utmIncidentService.changeStatus(utmIncident);
177-
return ResponseEntity.ok()
122+
@AuditEvent(
123+
attemptType = ApplicationEventType.INCIDENT_UPDATE_ATTEMPT,
124+
attemptMessage = "Attempt to update incident status initiated",
125+
successType = ApplicationEventType.INCIDENT_UPDATE_SUCCESS,
126+
successMessage = "Incident status updated successfully"
127+
)
128+
public ResponseEntity<UtmIncident> updateUtmIncident(@Valid @RequestBody UtmIncident utmIncident) {
129+
130+
if (utmIncident.getId() == null) {
131+
throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull");
132+
}
133+
UtmIncident result = utmIncidentService.changeStatus(utmIncident);
134+
135+
return ResponseEntity.ok()
178136
.headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, utmIncident.getId().toString()))
179137
.body(result);
180-
} catch (Exception e) {
181-
String msg = ctx + ": " + e.getMessage();
182-
log.error(msg);
183-
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);
184-
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(HeaderUtil.createFailureAlert(CLASS_NAME, null, msg)).body(null);
185-
}
186138
}
187139

188140
/**
@@ -194,18 +146,10 @@ public ResponseEntity<UtmIncident> updateUtmIncident(@Valid @RequestBody UtmInci
194146
*/
195147
@GetMapping("/utm-incidents")
196148
public ResponseEntity<List<UtmIncident>> getAllUtmIncidents(UtmIncidentCriteria criteria, Pageable pageable) {
197-
final String ctx = ".getAllUtmIncidents";
198-
try {
199-
log.debug("REST request to get UtmIncidents by criteria: {}", criteria);
200-
Page<UtmIncident> page = utmIncidentQueryService.findByCriteria(criteria, pageable);
201-
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/utm-incidents");
202-
return ResponseEntity.ok().headers(headers).body(page.getContent());
203-
} catch (Exception e) {
204-
String msg = ctx + ": " + e.getMessage();
205-
log.error(msg);
206-
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);
207-
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(HeaderUtil.createFailureAlert(CLASS_NAME, null, msg)).body(null);
208-
}
149+
150+
Page<UtmIncident> page = utmIncidentQueryService.findByCriteria(criteria, pageable);
151+
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/utm-incidents");
152+
return ResponseEntity.ok().headers(headers).body(page.getContent());
209153
}
210154

211155
/**
@@ -215,15 +159,7 @@ public ResponseEntity<List<UtmIncident>> getAllUtmIncidents(UtmIncidentCriteria
215159
*/
216160
@GetMapping("/utm-incidents/users-assigned")
217161
public ResponseEntity<List<IncidentUserAssignedDTO>> getAllUserAssigned() {
218-
final String ctx = ".getAllUserAssigned";
219-
try {
220-
return ResponseEntity.ok().body(utmIncidentQueryService.getAllUsersAssigned());
221-
} catch (Exception e) {
222-
String msg = ctx + ": " + e.getMessage();
223-
log.error(msg);
224-
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);
225-
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(HeaderUtil.createFailureAlert(CLASS_NAME, null, msg)).body(null);
226-
}
162+
return ResponseEntity.ok().body(utmIncidentQueryService.getAllUsersAssigned());
227163
}
228164

229165
/**
@@ -234,16 +170,9 @@ public ResponseEntity<List<IncidentUserAssignedDTO>> getAllUserAssigned() {
234170
*/
235171
@GetMapping("/utm-incidents/{id}")
236172
public ResponseEntity<UtmIncident> getUtmIncident(@PathVariable Long id) {
237-
final String ctx = ".getUtmIncident";
238-
try {
239-
log.debug("REST request to get UtmIncident : {}", id);
240-
Optional<UtmIncident> utmIncident = utmIncidentService.findOne(id);
241-
return ResponseUtil.wrapOrNotFound(utmIncident);
242-
} catch (Exception e) {
243-
String msg = ctx + ": " + e.getMessage();
244-
log.error(msg);
245-
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);
246-
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(HeaderUtil.createFailureAlert(CLASS_NAME, null, msg)).body(null);
247-
}
173+
174+
Optional<UtmIncident> utmIncident = utmIncidentService.findOne(id);
175+
return tech.jhipster.web.util.ResponseUtil.wrapOrNotFound(utmIncident);
176+
248177
}
249178
}

0 commit comments

Comments
 (0)