Skip to content

refactor: clean up Incident module code#109

Merged
SandraNelj merged 2 commits into
mainfrom
fix/refactorIncident-class
Apr 25, 2026
Merged

refactor: clean up Incident module code#109
SandraNelj merged 2 commits into
mainfrom
fix/refactorIncident-class

Conversation

@SandraNelj

@SandraNelj SandraNelj commented Apr 25, 2026

Copy link
Copy Markdown
Contributor
  • Replace manual getters/setters with @Getter/@Setter in Incident entity
  • Replace manual constructor with @requiredargsconstructor in IncidentService
  • Extract getUser() helper method in IncidentController
  • Standardize @AuthenticationPrincipal parameter name to userDetails
  • Replace SecurityContextHolder with @AuthenticationPrincipal in getIncidentById
  • Extract validateNotClosed() and validateHandlerOrAdmin() helper methods
  • Extract string literals to constants (TARGET_TYPE, INCIDENT_PREFIX, NOT_FOUND_MESSAGE)
  • Replace lambda with method reference (Objects::nonNull) in IncidentResponse
  • Replace unnamed exception variable with unnamed pattern (_)
  • Fix SonarQube warnings for logging and null-safety annotations

Summary by CodeRabbit

  • Bug Fixes

    • Enhanced authentication and authorization validation for incident operations
  • Refactor

    • Simplified incident entity implementation
    • Standardized validation checks, error handling, and audit logging across incident workflows
    • Centralized authorization logic for improved consistency
  • Tests

    • Updated security context handling in incident endpoint tests

- Replace manual getters/setters with @Getter/@Setter in Incident entity
- Replace manual constructor with @requiredargsconstructor in IncidentService
- Extract getUser() helper method in IncidentController
- Standardize @AuthenticationPrincipal parameter name to userDetails
- Replace SecurityContextHolder with @AuthenticationPrincipal in getIncidentById
- Extract validateNotClosed() and validateHandlerOrAdmin() helper methods
- Extract string literals to constants (TARGET_TYPE, INCIDENT_PREFIX, NOT_FOUND_MESSAGE)
- Replace lambda with method reference (Objects::nonNull) in IncidentResponse
- Replace unnamed exception variable with unnamed pattern (_)
- Fix SonarQube warnings for logging and null-safety annotations
@SandraNelj SandraNelj self-assigned this Apr 25, 2026
@coderabbitai

coderabbitai Bot commented Apr 25, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@SandraNelj has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 34 minutes and 5 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 34 minutes and 5 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e5c376c5-47c8-4a0b-a17a-33300f1c1c8e

📥 Commits

Reviewing files that changed from the base of the PR and between 2f7d3b3 and 4aa75eb.

📒 Files selected for processing (4)
  • src/main/java/org/example/team6backend/incident/controller/IncidentController.java
  • src/main/java/org/example/team6backend/incident/dto/IncidentResponse.java
  • src/main/java/org/example/team6backend/incident/service/IncidentService.java
  • src/test/java/org/example/team6backend/incident/controller/IncidentControllerTest.java
📝 Walkthrough

Walkthrough

The incident module undergoes refactoring to improve code maintainability. Lombok adoption replaces manual constructors and accessors in Incident and IncidentService, while a new getUser() helper method centralizes authenticated user resolution in IncidentController. IncidentService adds validation helpers for authorization and state checks, standardizing error handling and audit logging across operations. Minor adjustments to document filtering and test authentication setup complete the changes.

Changes

Cohort / File(s) Summary
Controller Authentication Enhancement
src/main/java/org/example/team6backend/incident/controller/IncidentController.java
Added getUser() helper method that resolves authenticated AppUser from @AuthenticationPrincipal or SecurityContextHolder, falling back gracefully. Updated incident creation, listing, assignment, and status-update endpoints to use this helper. Refactored getIncidentById to use pattern matching for the authenticated principal.
Service Refactoring with Validation
src/main/java/org/example/team6backend/incident/service/IncidentService.java
Adopted Lombok's @RequiredArgsConstructor to replace manual constructor. Introduced validateHandlerOrAdmin() and validateNotClosed() helper methods for centralized authorization and incident-state validation. Standardized error handling, audit logging format (using TARGET_TYPE and INCIDENT_PREFIX), and notification text across all incident operations.
Entity Lombok Adoption
src/main/java/org/example/team6backend/incident/entity/Incident.java
Replaced all explicit getter and setter methods with Lombok's @Getter and @Setter annotations. Entity fields and JPA lifecycle callbacks remain unchanged; boilerplate code is reduced significantly.
DTO Document Filtering
src/main/java/org/example/team6backend/incident/dto/IncidentResponse.java
Refactored document filtering in fromEntityWithDocuments to use Objects::nonNull instead of inline lambda. Updated exception handling syntax to discard caught variable.
Test Authentication Updates
src/test/java/org/example/team6backend/incident/controller/IncidentControllerTest.java
Replaced @WithMockUser annotation with manual SecurityContextHolder population in getIncidentById() test. Relaxed anonymous access assertion from 401 Unauthorized to general 4xx client error.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • PR #108: Adds helper method that resolves authenticated AppUser from @AuthenticationPrincipal or SecurityContext, mirroring the same authentication resolution pattern introduced in this PR.
  • PR #70: Modifies IncidentController's handling of authenticated user and updates service call signatures to accept AppUser parameters.
  • PR #27: Original Incident module addition; this PR continues to refactor and enhance the module with Lombok adoption and centralized validation logic.

Poem

🐰 Lombok hops in with a bouncing stride,
Getters and setters? Cast aside!
Helpers resolve users from context's deep,
Validators guard what we must keep,
Cleaner code makes this rabbit leap! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.85% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'refactor: clean up Incident module code' is vague and generic, using the term 'clean up' without specifying what was actually refactored. Replace 'clean up' with specific changes: 'refactor: replace manual getters/setters with Lombok annotations in Incident module' or similar detail.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/refactorIncident-class

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/org/example/team6backend/incident/controller/IncidentController.java (1)

151-167: 🛠️ Refactor suggestion | 🟠 Major

closeIncident / resolveIncident bypass the new getUser(...) helper.

These two endpoints still call userDetails.getUser() directly. If userDetails is null (e.g., principal resolution edge cases like the ones the helper was specifically introduced to handle), this throws NPE instead of returning 401. For consistency with createIncident, assignIncident, unassignIncident, updateStatus, etc., route them through getUser(...) too.

♻️ Suggested change
 	public ResponseEntity<IncidentResponse> closeIncident(`@PathVariable` Long incidentId,
 			`@AuthenticationPrincipal` CustomUserDetails userDetails) {
 		log.info("PATCH /api/incidents/{}/close - Closing incident", incidentId);
-		Incident closedIncident = incidentService.closeIncident(incidentId, userDetails.getUser());
+		Incident closedIncident = incidentService.closeIncident(incidentId, getUser(userDetails));
 		return ResponseEntity.ok(IncidentResponse.fromEntityBasic(closedIncident));
 	}
 ...
 	public ResponseEntity<IncidentResponse> resolveIncident(`@PathVariable` Long incidentId,
 			`@AuthenticationPrincipal` CustomUserDetails userDetails) {
 		log.info("PATCH /api/incidents/{}/resolve - Resolving incident", incidentId);
-		Incident resolvedIncident = incidentService.resolveIncident(incidentId, userDetails.getUser());
+		Incident resolvedIncident = incidentService.resolveIncident(incidentId, getUser(userDetails));
 		return ResponseEntity.ok(IncidentResponse.fromEntityBasic(resolvedIncident));
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/org/example/team6backend/incident/controller/IncidentController.java`
around lines 151 - 167, The closeIncident and resolveIncident methods call
userDetails.getUser() directly which can NPE; instead, use the controller's
existing getUser(...) helper to resolve the authenticated user and return 401
when it is absent. Update closeIncident(...) and resolveIncident(...) to call
getUser(userDetails) (or whatever the helper signature is) and pass the returned
User to incidentService.closeIncident(...) /
incidentService.resolveIncident(...), keeping the existing logging and
ResponseEntity.ok(...) flow.
🧹 Nitpick comments (1)
src/main/java/org/example/team6backend/incident/service/IncidentService.java (1)

144-146: getById skipped the NOT_FOUND_MESSAGE standardization.

Every other lookup in this file (deleteIncident, assignIncidentToHandler, updateIncidentStatus, unassignIncident, closeIncident, resolveIncident) was migrated to NOT_FOUND_MESSAGE + incidentId, but getById still throws a generic "Not found". Worth aligning so the error surface is uniform and consumers can rely on a single message format.

♻️ Suggested change
-	public Incident getById(Long id, AppUser user) {
-		Incident incident = incidentRepository.findByIdWithDocuments(id)
-				.orElseThrow(() -> new ResourceNotFoundException("Not found"));
+	public Incident getById(Long id, AppUser user) {
+		Incident incident = incidentRepository.findByIdWithDocuments(id)
+				.orElseThrow(() -> new ResourceNotFoundException(NOT_FOUND_MESSAGE + id));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/org/example/team6backend/incident/service/IncidentService.java`
around lines 144 - 146, The getById method in IncidentService throws a hardcoded
"Not found"; change it to use the standardized NOT_FOUND_MESSAGE concatenated
with the incident id to match other lookups: update the
ResourceNotFoundException thrown in getById (after
incidentRepository.findByIdWithDocuments(id)) to throw new
ResourceNotFoundException(NOT_FOUND_MESSAGE + id) so the error format is
consistent with deleteIncident, assignIncidentToHandler, updateIncidentStatus,
unassignIncident, closeIncident and resolveIncident.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/java/org/example/team6backend/incident/controller/IncidentController.java`:
- Around line 46-56: In getUser(CustomUserDetails userDetails) remove the
System.out.println debug call and avoid dereferencing userDetails before
null-check: first check if (userDetails == null) and only then fall back to
SecurityContextHolder auth lookup (as done now), and if auth principal is a
CustomUserDetails cd, verify cd.getUser() is non-null before returning it; if
cd.getUser() is null or no auth principal is present throw new
ResponseStatusException(HttpStatus.UNAUTHORIZED, "Authentication required"). If
you want to keep a debug message use the class SLF4J logger at debug level
(log.debug(...)) after confirming userDetails != null.

In `@src/main/java/org/example/team6backend/incident/dto/IncidentResponse.java`:
- Around line 63-66: The catch block in IncidentResponse that currently reads
"catch (Exception _)" swallows all exceptions and should at minimum log the
throwable before falling back to response.setHasDocuments(false) and
response.setDocuments(new ArrayList<>()); add an SLF4J logger to the class (or
move this mapping out of the DTO into a service/mapper) and change the catch to
log the exception at warn or debug level (including the exception object) so
failures like LazyInitializationException are visible while preserving the
fallback behavior.

In
`@src/main/java/org/example/team6backend/incident/service/IncidentService.java`:
- Around line 253-254: Replace the 3-arg auditLogService.log calls for the
security-relevant operations UPDATE_STATUS, UNASSIGN_INCIDENT, CLOSE_INCIDENT,
and RESOLVE_INCIDENT with the 5-arg overload that includes the target type and
target id so audit filtering works; specifically, for each call that currently
invokes auditLogService.log(operation, currentUser.getName() + " changed " +
INCIDENT_PREFIX + incidentId + ... , currentUser) (and the analogous message
patterns for unassign/close/resolve), pass the Incident target type constant and
incidentId as the fourth and fifth arguments (i.e.,
auditLogService.log(operation, message, currentUser, TARGET_TYPE, incidentId)),
keeping the existing message, currentUser, INCIDENT_PREFIX and incidentId
variables intact.

In
`@src/test/java/org/example/team6backend/incident/controller/IncidentControllerTest.java`:
- Around line 132-135: In IncidentControllerTest::getById_shouldBlockIfAnonymous
replace the broad .andExpect(status().is4xxClientError()) with a specific
expected status to avoid masking regressions (e.g.,
.andExpect(status().isUnauthorized()) or .andExpect(status().isForbidden())
depending on the security contract you intend); update the assertion to the
precise status that the controller/security layer should return for anonymous
users so the test fails if it changes unexpectedly.

---

Outside diff comments:
In
`@src/main/java/org/example/team6backend/incident/controller/IncidentController.java`:
- Around line 151-167: The closeIncident and resolveIncident methods call
userDetails.getUser() directly which can NPE; instead, use the controller's
existing getUser(...) helper to resolve the authenticated user and return 401
when it is absent. Update closeIncident(...) and resolveIncident(...) to call
getUser(userDetails) (or whatever the helper signature is) and pass the returned
User to incidentService.closeIncident(...) /
incidentService.resolveIncident(...), keeping the existing logging and
ResponseEntity.ok(...) flow.

---

Nitpick comments:
In
`@src/main/java/org/example/team6backend/incident/service/IncidentService.java`:
- Around line 144-146: The getById method in IncidentService throws a hardcoded
"Not found"; change it to use the standardized NOT_FOUND_MESSAGE concatenated
with the incident id to match other lookups: update the
ResourceNotFoundException thrown in getById (after
incidentRepository.findByIdWithDocuments(id)) to throw new
ResourceNotFoundException(NOT_FOUND_MESSAGE + id) so the error format is
consistent with deleteIncident, assignIncidentToHandler, updateIncidentStatus,
unassignIncident, closeIncident and resolveIncident.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 153ab0d4-5845-40e7-856c-772289584b4b

📥 Commits

Reviewing files that changed from the base of the PR and between 2eb92fc and 2f7d3b3.

📒 Files selected for processing (5)
  • src/main/java/org/example/team6backend/incident/controller/IncidentController.java
  • src/main/java/org/example/team6backend/incident/dto/IncidentResponse.java
  • src/main/java/org/example/team6backend/incident/entity/Incident.java
  • src/main/java/org/example/team6backend/incident/service/IncidentService.java
  • src/test/java/org/example/team6backend/incident/controller/IncidentControllerTest.java

Comment thread src/main/java/org/example/team6backend/incident/dto/IncidentResponse.java Outdated
Comment thread src/main/java/org/example/team6backend/incident/service/IncidentService.java Outdated
- Fix anonymous user test to expect 401 instead of generic 4xx
- Add targetType and targetId to all audit log calls in IncidentService
- Add warning log when document loading fails in IncidentResponse
- Remove debug System.out.println from getUser() helper
- Add null check for cd.getUser() in getUser() fallback path
@SandraNelj
SandraNelj merged commit 687d1d3 into main Apr 25, 2026
3 checks passed
@SandraNelj
SandraNelj deleted the fix/refactorIncident-class branch April 25, 2026 11:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant