Skip to content

Refactor and pagination#34

Merged
SandraNelj merged 2 commits into
mainfrom
feature/incident
Mar 30, 2026
Merged

Refactor and pagination#34
SandraNelj merged 2 commits into
mainfrom
feature/incident

Conversation

@SandraNelj

@SandraNelj SandraNelj commented Mar 30, 2026

Copy link
Copy Markdown
Contributor
  • Added updatedAt field to Incident entity
  • Updated IncidentService to support pagination (Pageable) for:
    • All incidents
    • CreatedBy incidents (my incidents)
    • AssignedTo incidents
  • Updated IncidentController to handle paginated responses and map to IncidentResponse
  • Added @PreAuthorize annotations for role-based access control on endpoints
  • Updated repository methods to support Pageable
  • Configured Flyway to handle baseline-on-migrate for existing database

Summary by CodeRabbit

  • New Features

    • Incident listings now support pagination for faster browsing of large lists.
    • Added automatic tracking of incident creation and update timestamps.
  • Improvements

    • Dedicated, role-restricted views for residents, handlers, and administrators provide tailored incident lists.

- Updated IncidentService to support pagination (Pageable) for:
    - All incidents
    - CreatedBy incidents (my incidents)
    - AssignedTo incidents
- Updated IncidentController to handle paginated responses and map to IncidentResponse
- Added @PreAuthorize annotations for role-based access control on endpoints
- Updated repository methods to support Pageable
- Configured Flyway to handle baseline-on-migrate for existing database
@coderabbitai

coderabbitai Bot commented Mar 30, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e009eccf-8c0a-4ba2-8c5c-1cb962f958e2

📥 Commits

Reviewing files that changed from the base of the PR and between 8ba0ebd and f9be81a.

📒 Files selected for processing (2)
  • src/main/java/org/example/team6backend/incident/entity/Incident.java
  • src/main/java/org/example/team6backend/incident/service/IncidentService.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/org/example/team6backend/incident/entity/Incident.java
  • src/main/java/org/example/team6backend/incident/service/IncidentService.java

📝 Walkthrough

Walkthrough

Replaces an unpaginated incident list endpoint with three role-restricted, paginated endpoints and moves service/repository methods to pageable signatures. Adds createdAt/updatedAt timestamps, explicit column/join mappings on Incident, Flyway baseline config, and security-aware user resolution in service methods.

Changes

Cohort / File(s) Summary
Incident Controller
src/main/java/org/example/team6backend/incident/controller/IncidentController.java
Removed unpaginated GET /api/incidents. Added three paginated, role-restricted endpoints: GET /myincident (RESIDENT), GET /assigned (HANDLER), GET /admin (ADMIN), each accepting Pageable and returning Page<IncidentResponse>; added Spring Security and paging imports.
Incident Entity
src/main/java/org/example/team6backend/incident/entity/Incident.java
Added explicit @Column names for fields (incident_category, incident_status, created_at, updated_at), updatedAt field with getter/setter, explicit @JoinColumn names for associations (created_by_id, modified_by_id, assigned_to_id), and lifecycle callbacks to set timestamps on persist/update.
Incident Repository
src/main/java/org/example/team6backend/incident/repository/IncidentRepository.java
Changed repository query signatures to support pagination: findByCreatedBy(AppUser, Pageable) and findByAssignedTo(AppUser, Pageable) now return Page<Incident> instead of List<Incident>. Added Page/Pageable imports.
Incident Service
src/main/java/org/example/team6backend/incident/service/IncidentService.java
Converted service retrieval methods to pageable variants returning Page<Incident>: findByCreatedBy(Pageable), findByAssignedTo(Pageable), findAll(Pageable). Service now resolves current AppUser from SecurityContextHolder, applies default sort when needed, and sets updatedAt in createIncident.
Configuration
src/main/resources/application.yml
Added spring.flyway.baseline-on-migrate: true to enable Flyway baseline-on-migrate behavior.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Controller as IncidentController
    participant Security as SecurityContext
    participant Service as IncidentService
    participant Repository as IncidentRepository
    participant Database

    Client->>Controller: GET /myincident?page=0&size=10
    Controller->>Controller: `@PreAuthorize` checks RESIDENT role
    Controller->>Service: findByCreatedBy(pageable)
    Service->>Security: SecurityContextHolder.getContext()
    Security-->>Service: CurrentUserDetails/AppUser
    Service->>Repository: findByCreatedBy(user, pageable)
    Repository->>Database: SELECT ... WHERE created_by_id = ? LIMIT/OFFSET
    Database-->>Repository: paginated Incident rows
    Repository-->>Service: Page<Incident>
    Service-->>Controller: Page<Incident> (with default sort applied)
    Controller->>Controller: map Page<Incident> -> Page<IncidentResponse>
    Controller-->>Client: Page<IncidentResponse> + pagination metadata
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐇 I hopped through code with whiskers bright,
Pages now bloom in role-lit light,
Handlers, residents, admins each roam,
Timestamps tucked safe in every home,
Hooray — small hops, big structured delight! 🎉

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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 and pagination' is vague and generic, using non-descriptive terms that don't convey meaningful information about the specific changes made. Use a more specific title that describes the primary change, such as 'Add pagination to incident endpoints with role-based access control' or 'Implement paginated incident queries with security controls'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/incident

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: 2

🧹 Nitpick comments (3)
src/main/java/org/example/team6backend/incident/repository/IncidentRepository.java (1)

13-14: Back these new paginated filters with indexes.

findByCreatedBy(...) and findByAssignedTo(...) are now user-facing list paths. V3__create_incident_table.sql creates created_by_id and assigned_to_id, but no supporting indexes, so both the page query and the count query will degrade into table scans as incident grows. Please add indexes in a follow-up migration, ideally matching whatever default sort you settle on.

🤖 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/repository/IncidentRepository.java`
around lines 13 - 14, Add supporting indexes for the new paginated filters so
queries for findByCreatedBy(AppUser, Pageable) and findByAssignedTo(AppUser,
Pageable) don't degenerate into full table scans; create a new migration (e.g.,
V4__add_incident_indexes.sql) that adds indexes on incident(created_by_id) and
incident(assigned_to_id) and, if you choose a default sort (e.g., created_at
DESC), add composite indexes matching that sort such as incident(created_by_id,
created_at) and incident(assigned_to_id, created_at) to optimize both the
pageable content query and the count query.
src/main/resources/application.yml (1)

20-23: Verify this Flyway baseline strategy before enabling it globally.

baseline-on-migrate is only safe if the baseline version matches the schema that's already live. With versioned migrations already checked in, this flag alone can make the first Flyway run against a non-empty database ambiguous. Please set the matching baseline version or isolate this to the one-time bootstrap environment.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/resources/application.yml` around lines 20 - 23, The Flyway config
enabling baseline-on-migrate is risky; either set an explicit matching baseline
version with the Flyway property baseline-version to the live schema version (so
baseline-on-migrate: true is safe), or remove/disable baseline-on-migrate from
global configuration and move it into a one-time bootstrap profile (e.g., an
application-bootstrap profile or environment-specific config) so only the
bootstrap environment uses baseline-on-migrate; update the configuration keys
flyway.baseline-on-migrate and flyway.baseline-version (or place them under a
dedicated Spring profile) accordingly.
src/main/java/org/example/team6backend/incident/controller/IncidentController.java (1)

24-26: The POST /api/incidents endpoint is already protected via URL-level authentication.

SecurityConfig.securityFilterChain() specifies .anyRequest().authenticated() (line 36), which requires authentication for all requests except those explicitly permitted. Since /api/incidents is not in the permitAll list, the endpoint is protected and will return 401/403 before reaching the service layer.

However, adding @PreAuthorize("hasRole('RESIDENT')") to createIncident() would improve consistency with the three GET endpoints in this controller and make the access control contract explicit rather than implicit.

🤖 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 24 - 26, The createIncident endpoint in IncidentController (method
createIncident) lacks the explicit role-based annotation; add the
`@PreAuthorize`("hasRole('RESIDENT')") annotation to the createIncident(`@Valid`
`@RequestBody` IncidentRequest incidentRequest) method so access is explicitly
restricted to users with the RESIDENT role (matching the existing GET
endpoints), and ensure the class imports and method-level security is enabled so
the annotation is honored.
🤖 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/entity/Incident.java`:
- Around line 37-41: The Incident entity's timestamps are not maintained
automatically; add JPA lifecycle callbacks to set createdAt and updatedAt
consistently: implement a `@PrePersist` method (e.g., prePersist or
setTimestampsOnCreate) that sets createdAt and updatedAt to LocalDateTime.now()
when the entity is first persisted, and a `@PreUpdate` method (e.g., preUpdate or
setUpdatedTimestamp) that updates updatedAt to LocalDateTime.now() on every
update; follow the same pattern used in AppUser.java and place these methods
inside the Incident class so any persist/update path will maintain the createdAt
and updatedAt fields.

In
`@src/main/java/org/example/team6backend/incident/service/IncidentService.java`:
- Around line 39-57: IncidentService's pagination methods (findAll,
findByCreatedBy, findByAssignedTo) pass the incoming Pageable straight to the
repository, which can produce unstable page boundaries when no sort is provided;
add a private helper (e.g., ensureDefaultSort(Pageable)) in IncidentService that
checks pageable.getSort().isUnsorted() and, if unsorted, returns a new
PageRequest preserving page number and size but adding a stable default Sort
(for example Sort.by("id").ascending() or Sort.by("createdAt").descending());
call this helper from each of the three methods before delegating to
incidentRepository.findAll/findByCreatedBy/findByAssignedTo so every query uses
a deterministic sort when the client omits one.

---

Nitpick comments:
In
`@src/main/java/org/example/team6backend/incident/controller/IncidentController.java`:
- Around line 24-26: The createIncident endpoint in IncidentController (method
createIncident) lacks the explicit role-based annotation; add the
`@PreAuthorize`("hasRole('RESIDENT')") annotation to the createIncident(`@Valid`
`@RequestBody` IncidentRequest incidentRequest) method so access is explicitly
restricted to users with the RESIDENT role (matching the existing GET
endpoints), and ensure the class imports and method-level security is enabled so
the annotation is honored.

In
`@src/main/java/org/example/team6backend/incident/repository/IncidentRepository.java`:
- Around line 13-14: Add supporting indexes for the new paginated filters so
queries for findByCreatedBy(AppUser, Pageable) and findByAssignedTo(AppUser,
Pageable) don't degenerate into full table scans; create a new migration (e.g.,
V4__add_incident_indexes.sql) that adds indexes on incident(created_by_id) and
incident(assigned_to_id) and, if you choose a default sort (e.g., created_at
DESC), add composite indexes matching that sort such as incident(created_by_id,
created_at) and incident(assigned_to_id, created_at) to optimize both the
pageable content query and the count query.

In `@src/main/resources/application.yml`:
- Around line 20-23: The Flyway config enabling baseline-on-migrate is risky;
either set an explicit matching baseline version with the Flyway property
baseline-version to the live schema version (so baseline-on-migrate: true is
safe), or remove/disable baseline-on-migrate from global configuration and move
it into a one-time bootstrap profile (e.g., an application-bootstrap profile or
environment-specific config) so only the bootstrap environment uses
baseline-on-migrate; update the configuration keys flyway.baseline-on-migrate
and flyway.baseline-version (or place them under a dedicated Spring profile)
accordingly.
🪄 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: d7b77b6d-d16b-4fdf-b1cc-8a3ae443bed8

📥 Commits

Reviewing files that changed from the base of the PR and between 2bbb5aa and 8ba0ebd.

📒 Files selected for processing (5)
  • src/main/java/org/example/team6backend/incident/controller/IncidentController.java
  • src/main/java/org/example/team6backend/incident/entity/Incident.java
  • src/main/java/org/example/team6backend/incident/repository/IncidentRepository.java
  • src/main/java/org/example/team6backend/incident/service/IncidentService.java
  • src/main/resources/application.yml

Comment thread src/main/java/org/example/team6backend/incident/service/IncidentService.java Outdated
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