Skip to content

Feature/visualize comment log and file log#56

Merged
Martin-E-Karlsson merged 5 commits into
mainfrom
feature/visualize-comment-log-and-file-log
Apr 27, 2026
Merged

Feature/visualize comment log and file log#56
Martin-E-Karlsson merged 5 commits into
mainfrom
feature/visualize-comment-log-and-file-log

Conversation

@Martin-E-Karlsson

@Martin-E-Karlsson Martin-E-Karlsson commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

Release Notes

  • New Features
    • Added dedicated audit log pages for comments and files with filtering by event type and date range
    • Extended SYSADMIN role permissions to perform visa operations including approval, rejection, information requests, and handler assignment
    • Added navigation links to access new comment and file audit logs

- Implemented findFiltered service methods CommentLogService and FileLogService
- Implemented sysadmin accessible end points /log/comment and /log/file
- Updated header with links to new endpoints
- Created matching html pages for File Log and Comment Log
- Created tests for service methods and controller
Feature: Comment Log now links to the Visa Case where the comment was made
@Martin-E-Karlsson Martin-E-Karlsson linked an issue Apr 27, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Apr 27, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@Martin-E-Karlsson has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 2 minutes and 14 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ 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: a74b0678-879a-45a7-8cce-683e53a75ead

📥 Commits

Reviewing files that changed from the base of the PR and between 745e17c and daadfba.

📒 Files selected for processing (19)
  • src/main/java/org/example/visacasemanagementsystem/audit/service/CommentLogService.java
  • src/main/java/org/example/visacasemanagementsystem/audit/service/FileLogService.java
  • src/main/java/org/example/visacasemanagementsystem/audit/service/UserLogService.java
  • src/main/java/org/example/visacasemanagementsystem/audit/service/VisaLogService.java
  • src/main/java/org/example/visacasemanagementsystem/visa/service/VisaService.java
  • src/main/resources/static/css/components.css
  • src/main/resources/templates/fragments/cases.html
  • src/main/resources/templates/fragments/log-page.html
  • src/main/resources/templates/log/comment.html
  • src/main/resources/templates/log/file.html
  • src/main/resources/templates/log/user.html
  • src/main/resources/templates/log/visa.html
  • src/main/resources/templates/profile/edit.html
  • src/main/resources/templates/user/list.html
  • src/main/resources/templates/visa/apply-form.html
  • src/main/resources/templates/visa/details.html
  • src/main/resources/templates/visa/edit-form.html
  • src/main/resources/templates/visa/my-applications.html
  • src/test/java/org/example/visacasemanagementsystem/visa/VisaServiceIntegrationTest.java
📝 Walkthrough

Walkthrough

This PR extends the audit logging system by introducing dedicated comment and file log pages with filtering and pagination capabilities, updating service-layer authorization checks to include SYSADMIN roles, and implementing comprehensive test coverage for the new endpoints and filtering logic.

Changes

Cohort / File(s) Summary
Controller & Repository Layer
src/main/java/org/example/visacasemanagementsystem/audit/controller/LogViewController.java, src/main/java/org/example/visacasemanagementsystem/audit/repository/CommentLogRepository.java, src/main/java/org/example/visacasemanagementsystem/audit/repository/FileLogRepository.java
Added new /log/comment and /log/file endpoints to LogViewController; extended CommentLogRepository and FileLogRepository with JpaSpecificationExecutor to enable criteria-based filtering.
Audit Service Layer
src/main/java/org/example/visacasemanagementsystem/audit/service/CommentLogService.java, src/main/java/org/example/visacasemanagementsystem/audit/service/FileLogService.java, src/main/java/org/example/visacasemanagementsystem/audit/service/VisaLogService.java
Implemented findFiltered methods for CommentLogService and FileLogService with dynamic JPA specifications for optional event-type and date-range filtering; added @PreAuthorize("isAuthenticated()") to VisaLogService.findFiltered.
Visa Service Authorization
src/main/java/org/example/visacasemanagementsystem/visa/service/VisaService.java
Expanded authorization for six methods (findAll, approveVisa, rejectVisa, requestMoreInformation, assignHandler, findVisasByHandlerId) from hasRole('ADMIN') to hasAnyRole('ADMIN', 'SYSADMIN').
UI Templates
src/main/resources/templates/log/comment.html, src/main/resources/templates/log/file.html, src/main/resources/templates/fragments/header.html
Added new Thymeleaf templates for comment and file log pages with filter forms, dynamic status labels, and pagination; added SYSADMIN-only navigation links.
Test Suite
src/test/java/org/example/visacasemanagementsystem/audit/controller/LogViewControllerTest.java, src/test/java/org/example/visacasemanagementsystem/audit/service/CommentLogServiceTest.java, src/test/java/org/example/visacasemanagementsystem/audit/service/FileLogServiceTest.java
Added comprehensive tests for new audit log endpoints, filtering behavior, pagination, and JPA Specification composition validation.

Sequence Diagram(s)

sequenceDiagram
    participant User as User (Authenticated)
    participant Controller as LogViewController
    participant Service as CommentLogService/<br/>FileLogService
    participant Repo as Repository<br/>(JpaSpecificationExecutor)
    participant DB as Database

    User->>Controller: GET /log/comment?eventType=X&from=Y&to=Z&page=0
    activate Controller
    Controller->>Service: findFiltered(eventType, from, to, pageable)
    deactivate Controller
    activate Service
    Service->>Service: Build dynamic Specification<br/>(conditionally append predicates)
    Service->>Repo: findAll(specification, pageable)
    deactivate Service
    activate Repo
    Repo->>DB: Execute JPA Criteria Query<br/>(with optional filters)
    DB-->>Repo: Page<CommentLog>
    deactivate Repo
    activate Service
    Service->>Service: Map entities to DTOs
    Service-->>Controller: Page<CommentLogDTO>
    deactivate Service
    Controller-->>User: Render log/comment.html<br/>with filtered results & pagination
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • PR #52: Continues the log-feature work by extending LogViewController, introducing JpaSpecificationExecutor usage, and establishing the findFiltered service pattern.
  • PR #50: Introduces the underlying Comment/File entities, repositories, mappers, and base service implementations that this PR extends with specification-based querying and UI endpoints.
  • PR #53: Expands test coverage for CommentLogService and FileLogService with additional test cases for the newly added filtering functionality.

Suggested reviewers

  • eeebbaandersson
  • EdvinSandgren

Poem

🐰 Hops with joy through audit logs
Comments and files now filter with ease
SYSADMIN eyes can see all the logs
Pagination dances through specs and pleas
A rabbit approves this query spree! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main feature: adding visualization for comment log and file log audit pages, which aligns with the core changes (new controllers, services, templates).
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 feature/visualize-comment-log-and-file-log

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 (7)
src/main/resources/templates/log/file.html (1)

50-50: Move inline button styles into the existing component CSS.

Inlined style="width: auto; padding: 8px 16px;" on the submit button mixes presentation into the template and is duplicated in log/comment.html (line 50). Prefer a small modifier class (e.g., btn-submit btn-inline) defined in components.css.

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

In `@src/main/resources/templates/log/file.html` at line 50, Remove the inline
style on the submit button element and replace it with a small modifier class
(e.g., add "btn-inline" alongside "btn-submit" on the <button> in the template),
then add the corresponding CSS rule in the shared component stylesheet
(components.css) like .btn-inline { width: auto; padding: 8px 16px; } so
presentation is centralized; apply the same change to the duplicate button in
log/comment.html to avoid duplication.
src/main/resources/templates/log/comment.html (1)

1-123: Consider extracting a shared log-page Thymeleaf fragment.

log/comment.html and log/file.html are structurally identical: same header/count, same filter form, same pager, same empty state, with only the action URL, table columns, and event-type field differing. As more log views are added (or the existing ones evolve — pager styling, accessibility, sort controls, etc.), they will drift. A fragments/log-page.html fragment parameterized by the action URL, column definitions, and event-type field would remove the duplication.

Not blocking — the current template renders correctly and pagination/filter state is preserved.

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

In `@src/main/resources/templates/log/comment.html` around lines 1 - 123, Extract
the repeated page shell (header, log-count, filter form, pager and empty-state)
from log/comment.html and log/file.html into a parameterized Thymeleaf fragment
e.g. fragments/log-page.html; expose parameters for the form action URL, the
eventTypes/selectedEventType bindings, the date field names/values (from/to),
the logs Page object, and the table body/header insertion point. Replace the
duplicated markup in log/comment.html and log/file.html with a single th:replace
call to fragments/log-page.html, passing the specific action URL and a fragment
(or markup) for the table columns/rows and event-type select so each page
supplies only its differing pieces while the common pagination/filtering logic
lives in the fragment.
src/test/java/org/example/visacasemanagementsystem/audit/service/CommentLogServiceTest.java (2)

199-199: Nit: nullable(SingularAttribute.class) is broader than needed.

root.get(...) is invoked here with a SingularAttribute (via the JPA static metamodel CommentLog_), not with a null argument. any(SingularAttribute.class) (which excludes nulls) would more precisely express the expectation; nullable(...) is typically reserved for matchers that must also accept null. Same nit applies at lines 234, 269, and 317. Cosmetic only.

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

In
`@src/test/java/org/example/visacasemanagementsystem/audit/service/CommentLogServiceTest.java`
at line 199, Replace the broader nullable matcher with a non-null matcher where
the test expects a real SingularAttribute: change usages of
nullable(SingularAttribute.class) in the CommentLogServiceTest Mockito stubbings
(the when(root.get(...)) calls) to any(SingularAttribute.class) so the matcher
more precisely reflects that CommentLog_.<...> attributes (not null) are passed;
apply the same update to the other occurrences mentioned (the other
when(root.get(...)) stubbings in the test).

280-330: Composition assertion is tightly coupled to evaluation order — consider loosening or guarding.

The chained cb.and(eqPred, gtePred) → and1 and cb.and(and1, ltePred) → and2 stubs (Lines 321–322) replicate the production code's exact predicate-combining order. The inline comment already calls this out, which is good. However, Specification.and(...) is a default method implementation of Specification in Spring Data JPA; if that internal composition strategy ever changes (e.g. to flatten into a single cb.and(p1, p2, p3) varargs call, which cb.and supports), every "all filters" test in this file will silently break even though the production logic remains semantically equivalent.

Two lighter-touch options if you want to keep this future-proof without losing intent:

  • Assert only the three leaf predicate calls (cb.equal, cb.greaterThanOrEqualTo, cb.lessThanOrEqualTo) plus that actual is non-null, and drop the cb.and(...) chaining stubs.
  • Or use verify(cb, atLeastOnce()).and(any(Predicate.class), any(Predicate.class)) to assert that AND-composition occurred without pinning the exact pairing tree.

Not blocking — the comment makes the coupling explicit, and the same pattern is mirrored in FileLogServiceTest.

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

In
`@src/test/java/org/example/visacasemanagementsystem/audit/service/CommentLogServiceTest.java`
around lines 280 - 330, The test tightly couples to the exact
predicate-composition order by stubbing cb.and(eqPred, gtePred) -> and1 and
cb.and(and1, ltePred) -> and2 when capturing the Specification in
CommentLogServiceTest.findFiltered_shouldComposeAllPredicates_WhenAllFiltersAreSet;
loosen this by removing the cb.and(...) chaining stubs and either (a) assert the
three leaf predicate calls (verify cb.equal(eventTypePath,...),
cb.greaterThanOrEqualTo(...), cb.lessThanOrEqualTo(...)) and that
specCaptor.getValue().toPredicate(...) returns non-null, or (b) replace the
strict and stubs with a more permissive verify like verify(cb,
atLeastOnce()).and(any(Predicate.class), any(Predicate.class)) so the test
checks that AND-composition occurred without depending on the internal tree
shape of Specification.and.
src/main/java/org/example/visacasemanagementsystem/audit/controller/LogViewController.java (1)

138-145: Minor: pageTitle model attribute is set but not asserted in the new tests.

renderLogPage adds pageTitle (e.g. "Comment Log", "File Log") to the model, but LogViewControllerTest doesn't assert it for any endpoint (existing or new). If the templates rely on ${pageTitle} for the page heading or <title>, a regression that drops it from the controller would slip through web-layer tests. Consider adding model().attribute("pageTitle", "Comment Log") (and similar) to the existing default-render tests, or accept the gap as covered by template/integration tests.

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

In
`@src/main/java/org/example/visacasemanagementsystem/audit/controller/LogViewController.java`
around lines 138 - 145, The controller method renderLogPage adds a "pageTitle"
model attribute but tests in LogViewControllerTest do not assert it; update the
web-layer tests that exercise renderLogPage (e.g., the tests that hit endpoints
which call renderLogPage) to include assertions like
model().attribute("pageTitle", "<expected title>") for each endpoint (for
example "Comment Log" and "File Log") so the model contract is verified; locate
the controller method renderLogPage and the corresponding test methods in
LogViewControllerTest and add the model attribute assertions with the exact
expected strings.
src/test/java/org/example/visacasemanagementsystem/audit/controller/LogViewControllerTest.java (1)

338-429: Optional: asymmetric paging-edge coverage across the four endpoints.

Pagination clamping (MAX_PAGE_SIZE, negative page/size minima) lives in a single shared helper (buildPageable in LogViewController), so per-endpoint duplication isn't required for correctness. That said, the matrix is currently uneven:

Endpoint NoFilters Filters ExplicitPaging OversizedSize NegativePaging
/log/visa
/log/user
/log/comment
/log/file

If you want endpoint-symmetric guarantees (e.g. catching a future regression where a new handler stops calling buildPageable), add the missing oversized/negative cases. Otherwise relying on the /log/visa cases as the canonical clamping contract is fine — this is a code-organization choice, not a defect.

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

In
`@src/test/java/org/example/visacasemanagementsystem/audit/controller/LogViewControllerTest.java`
around lines 338 - 429, The test coverage is asymmetric for paging edge cases;
add tests that assert buildPageable clamping/negative handling for the remaining
endpoints by exercising /log/user, /log/comment, and /log/file with oversized
size and negative page/size params and verifying the corresponding
service.findFiltered calls receive the clamped Pageable; specifically add tests
similar to commentLog_AsSysadmin_WithOversizedPageSize_ShouldClampToMax and the
visa negative-page/size tests but targeting UserLogController methods (userLog
handler -> userLogService.findFiltered), CommentLogController handler
(commentLogService.findFiltered) and FileLogController handler
(fileLogService.findFiltered), using mockMvc.perform(get(...).param(...)) and
eq(PageRequest.of(..., clampedOrMinSize, Sort.by(...))) in verify to assert the
shared buildPageable behavior.
src/test/java/org/example/visacasemanagementsystem/audit/service/FileLogServiceTest.java (1)

1-335: Heavy duplication with CommentLogServiceTest — consider an abstract base or parameterized helper later.

This file is structurally identical to CommentLogServiceTest.java (same filter scenarios, same mocked Criteria API plumbing, same ArgumentCaptor patterns), differing only in entity/event-type names and DTO record shape. As more *LogServiceTest classes accrete, an abstract AbstractLogServiceFilteredTest<E extends Enum<E>, ENTITY, DTO> could host the four findFiltered_* cases and the createX_shouldPassSameEntityInstance case. Not blocking for this PR — flag it for a follow-up cleanup after Visa/User log services adopt the same findFiltered pattern.

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

In
`@src/test/java/org/example/visacasemanagementsystem/audit/service/FileLogServiceTest.java`
around lines 1 - 335, Tests in FileLogServiceTest duplicate
CommentLogServiceTest; extract common filtered-spec and instance-passing tests
into a generic base test class and reuse it. Create an abstract
AbstractLogServiceFilteredTest<E, ENTITY, DTO> that contains the findFiltered_*
tests (the ones invoking FileLogService#findFiltered behavior and capturing
Specification) and the createFileLog_shouldPassSameEntityInstance check,
parameterize it by enum/event type, entity and DTO, and have FileLogServiceTest
and CommentLogServiceTest extend it, overriding/implementing factory methods or
fields for the service under test, mapper, repository, example entity/DTO and
the enum constant; update the concrete tests to only include service-specific
cases not covered by the base class.
🤖 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/visacasemanagementsystem/audit/service/VisaLogService.java`:
- Line 47: The service-level authorization on VisaLogService (the `@PreAuthorize`
annotation on the findFiltered method) is too permissive and inconsistent with
the controller and PR summary; change the annotation on findFiltered (and
similarly on findAll in VisaLogService and on the findFiltered methods in
CommentLogService and FileLogService) from `@PreAuthorize`("isAuthenticated()") to
require the SYSADMIN role (e.g. `@PreAuthorize`("hasRole('SYSADMIN')" or the
equivalent expression used elsewhere) so the service layer enforces the same
SYSADMIN-only restriction as LogViewController.

In
`@src/main/java/org/example/visacasemanagementsystem/visa/service/VisaService.java`:
- Line 332: Review whether SYSADMIN should have business-action privileges; if
SYSADMIN should be limited to audit/system tasks, change the security
annotations on the business endpoints (methods approveVisa, rejectVisa,
requestMoreInformation, assignHandler in VisaService) to restrict to ADMIN-only
(e.g., replace hasAnyRole('ADMIN','SYSADMIN') with an ADMIN-only expression such
as hasRole('ADMIN') or hasAnyRole('ADMIN')); if SYSADMINs are intentionally
allowed, leave as-is and add a comment documenting that SYSADMINs may be
assigned as handlers so reviewers know the choice.

---

Nitpick comments:
In
`@src/main/java/org/example/visacasemanagementsystem/audit/controller/LogViewController.java`:
- Around line 138-145: The controller method renderLogPage adds a "pageTitle"
model attribute but tests in LogViewControllerTest do not assert it; update the
web-layer tests that exercise renderLogPage (e.g., the tests that hit endpoints
which call renderLogPage) to include assertions like
model().attribute("pageTitle", "<expected title>") for each endpoint (for
example "Comment Log" and "File Log") so the model contract is verified; locate
the controller method renderLogPage and the corresponding test methods in
LogViewControllerTest and add the model attribute assertions with the exact
expected strings.

In `@src/main/resources/templates/log/comment.html`:
- Around line 1-123: Extract the repeated page shell (header, log-count, filter
form, pager and empty-state) from log/comment.html and log/file.html into a
parameterized Thymeleaf fragment e.g. fragments/log-page.html; expose parameters
for the form action URL, the eventTypes/selectedEventType bindings, the date
field names/values (from/to), the logs Page object, and the table body/header
insertion point. Replace the duplicated markup in log/comment.html and
log/file.html with a single th:replace call to fragments/log-page.html, passing
the specific action URL and a fragment (or markup) for the table columns/rows
and event-type select so each page supplies only its differing pieces while the
common pagination/filtering logic lives in the fragment.

In `@src/main/resources/templates/log/file.html`:
- Line 50: Remove the inline style on the submit button element and replace it
with a small modifier class (e.g., add "btn-inline" alongside "btn-submit" on
the <button> in the template), then add the corresponding CSS rule in the shared
component stylesheet (components.css) like .btn-inline { width: auto; padding:
8px 16px; } so presentation is centralized; apply the same change to the
duplicate button in log/comment.html to avoid duplication.

In
`@src/test/java/org/example/visacasemanagementsystem/audit/controller/LogViewControllerTest.java`:
- Around line 338-429: The test coverage is asymmetric for paging edge cases;
add tests that assert buildPageable clamping/negative handling for the remaining
endpoints by exercising /log/user, /log/comment, and /log/file with oversized
size and negative page/size params and verifying the corresponding
service.findFiltered calls receive the clamped Pageable; specifically add tests
similar to commentLog_AsSysadmin_WithOversizedPageSize_ShouldClampToMax and the
visa negative-page/size tests but targeting UserLogController methods (userLog
handler -> userLogService.findFiltered), CommentLogController handler
(commentLogService.findFiltered) and FileLogController handler
(fileLogService.findFiltered), using mockMvc.perform(get(...).param(...)) and
eq(PageRequest.of(..., clampedOrMinSize, Sort.by(...))) in verify to assert the
shared buildPageable behavior.

In
`@src/test/java/org/example/visacasemanagementsystem/audit/service/CommentLogServiceTest.java`:
- Line 199: Replace the broader nullable matcher with a non-null matcher where
the test expects a real SingularAttribute: change usages of
nullable(SingularAttribute.class) in the CommentLogServiceTest Mockito stubbings
(the when(root.get(...)) calls) to any(SingularAttribute.class) so the matcher
more precisely reflects that CommentLog_.<...> attributes (not null) are passed;
apply the same update to the other occurrences mentioned (the other
when(root.get(...)) stubbings in the test).
- Around line 280-330: The test tightly couples to the exact
predicate-composition order by stubbing cb.and(eqPred, gtePred) -> and1 and
cb.and(and1, ltePred) -> and2 when capturing the Specification in
CommentLogServiceTest.findFiltered_shouldComposeAllPredicates_WhenAllFiltersAreSet;
loosen this by removing the cb.and(...) chaining stubs and either (a) assert the
three leaf predicate calls (verify cb.equal(eventTypePath,...),
cb.greaterThanOrEqualTo(...), cb.lessThanOrEqualTo(...)) and that
specCaptor.getValue().toPredicate(...) returns non-null, or (b) replace the
strict and stubs with a more permissive verify like verify(cb,
atLeastOnce()).and(any(Predicate.class), any(Predicate.class)) so the test
checks that AND-composition occurred without depending on the internal tree
shape of Specification.and.

In
`@src/test/java/org/example/visacasemanagementsystem/audit/service/FileLogServiceTest.java`:
- Around line 1-335: Tests in FileLogServiceTest duplicate
CommentLogServiceTest; extract common filtered-spec and instance-passing tests
into a generic base test class and reuse it. Create an abstract
AbstractLogServiceFilteredTest<E, ENTITY, DTO> that contains the findFiltered_*
tests (the ones invoking FileLogService#findFiltered behavior and capturing
Specification) and the createFileLog_shouldPassSameEntityInstance check,
parameterize it by enum/event type, entity and DTO, and have FileLogServiceTest
and CommentLogServiceTest extend it, overriding/implementing factory methods or
fields for the service under test, mapper, repository, example entity/DTO and
the enum constant; update the concrete tests to only include service-specific
cases not covered by the base class.
🪄 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: f2eb8cdf-eb91-4618-993f-3688b8b3ccf0

📥 Commits

Reviewing files that changed from the base of the PR and between 8066468 and 745e17c.

📒 Files selected for processing (13)
  • src/main/java/org/example/visacasemanagementsystem/audit/controller/LogViewController.java
  • src/main/java/org/example/visacasemanagementsystem/audit/repository/CommentLogRepository.java
  • src/main/java/org/example/visacasemanagementsystem/audit/repository/FileLogRepository.java
  • src/main/java/org/example/visacasemanagementsystem/audit/service/CommentLogService.java
  • src/main/java/org/example/visacasemanagementsystem/audit/service/FileLogService.java
  • src/main/java/org/example/visacasemanagementsystem/audit/service/VisaLogService.java
  • src/main/java/org/example/visacasemanagementsystem/visa/service/VisaService.java
  • src/main/resources/templates/fragments/header.html
  • src/main/resources/templates/log/comment.html
  • src/main/resources/templates/log/file.html
  • src/test/java/org/example/visacasemanagementsystem/audit/controller/LogViewControllerTest.java
  • src/test/java/org/example/visacasemanagementsystem/audit/service/CommentLogServiceTest.java
  • src/test/java/org/example/visacasemanagementsystem/audit/service/FileLogServiceTest.java

* only non-null filters are added to the query, so Hibernate never has to
* bind a null enum parameter (which fails in Hibernate 6/7).
*/
@PreAuthorize("isAuthenticated()")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Service-level guard is weaker than the controller and inconsistent with the PR summary.

The new @PreAuthorize("isAuthenticated()") here (and on the sibling findFiltered methods in CommentLogService/FileLogService) lets any authenticated principal — including USER and ADMIN — invoke this method directly, even though LogViewController only exposes the page to SYSADMIN. The AI-generated summary also describes this PR as "updating service-layer authorization checks to include SYSADMIN roles", which doesn't match what the annotation actually expresses.

For defense in depth (and to align with the summary), consider tightening to the role that actually owns the audit-log surface, e.g.:

🔒 Suggested change
-    `@PreAuthorize`("isAuthenticated()")
+    `@PreAuthorize`("hasRole('SYSADMIN')")
     public Page<VisaLogDTO> findFiltered(VisaEventType eventType,

The existing findAll() annotation could reasonably be tightened in the same pass, since it's reached by the same SYSADMIN-only page.

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

In
`@src/main/java/org/example/visacasemanagementsystem/audit/service/VisaLogService.java`
at line 47, The service-level authorization on VisaLogService (the `@PreAuthorize`
annotation on the findFiltered method) is too permissive and inconsistent with
the controller and PR summary; change the annotation on findFiltered (and
similarly on findAll in VisaLogService and on the findFiltered methods in
CommentLogService and FileLogService) from `@PreAuthorize`("isAuthenticated()") to
require the SYSADMIN role (e.g. `@PreAuthorize`("hasRole('SYSADMIN')" or the
equivalent expression used elsewhere) so the service layer enforces the same
SYSADMIN-only restriction as LogViewController.

- Restricted all log service findFiltered methods to sysadmin only access
- Refactored components and styles from html files to stylesheets
- Restricted all log service findAll methods to sysadmin only access
- Added sysadmin authorization to tests utilizing log service findAll methods
- Extracted common elements from log templates to a log fragment
@Martin-E-Karlsson

Copy link
Copy Markdown
Contributor Author

@coderabbitai review the last two commits

@coderabbitai

coderabbitai Bot commented Apr 27, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the last two commits of the PR branch
gh pr view 56 --repo ithsjava25/visa-case-management-system --json headRefName,baseRefName,commits --jq '.commits[-2:]'

Length of output: 951


🏁 Script executed:

#!/bin/bash
# Get the diff for the last two commits
echo "=== COMMIT 1: 87c89e5c ==="
gh api repos/ithsjava25/visa-case-management-system/commits/87c89e5c72b662429bcd20b479f32ad173601537 --jq '.files[] | "FILE: \(.filename)\nSTATUS: \(.status)\nADDITIONS: \(.additions)\nDELETIONS: \(.deletions)\nPATCH:\n\(.patch // "(binary or too large)")\n---"'

echo ""
echo "=== COMMIT 2: 5fa14263 ==="
gh api repos/ithsjava25/visa-case-management-system/commits/5fa14263b8cff9499d71f2c39d765291aff3d922 --jq '.files[] | "FILE: \(.filename)\nSTATUS: \(.status)\nADDITIONS: \(.additions)\nDELETIONS: \(.deletions)\nPATCH:\n\(.patch // "(binary or too large)")\n---"'

Length of output: 58022


@Martin-E-Karlsson Here is my review of the last two commits (87c89e5c and 5fa14263):


Commit 1 — Restrict findFiltered to SYSADMIN + CSS refactoring

✅ What looks good

  • Clean, consistent tightening of findFiltered from isAuthenticated()hasRole('SYSADMIN') across all four log services.
  • The CSS consolidation into components.css is well-structured: utility classes like .file-upload-zone, .doc-list, .td-right, .mt-card, .hidden, and .btn-submit-inline are well-named and reusable.
  • Inline style="" attributes have been correctly eliminated from many templates (apply-form, edit-form, user/list, my-applications, profile/edit, etc.).

⚠️ Issue — visa/details.html still uses an inline <style> block

While many inline styles were removed from visa/details.html, the commit simultaneously adds new page-scoped rules directly to the <style> block at the top of the file (.admin-actions h3, .decision-form, .form-row, .no-comments, etc.) instead of placing them in components.css. This is inconsistent with the spirit of the refactoring done here and in the rest of the templates.


Commit 2 — Restrict findAll to SYSADMIN + log-page fragment

✅ What looks good

  • Excellent DRY refactoring — the new fragments/log-page.html fragment eliminates ~300+ lines of duplicated HTML across all four log templates. The parameter Javadoc inside the fragment is a nice touch.
  • The integration test helper authenticateAsSysadmin() is clean and correctly switches the security context only for the assertion phase, without affecting the action under test.
  • Explanatory comment added to VisaService for SYSADMIN inclusion is clear and valuable.

🚨 Potential security gap — UserLogService.findAll() not updated

The commit message says "Restricted all log service findAll methods to sysadmin only access", but UserLogService.java is not present in this commit's changeset. Commit 1 already updated UserLogService.findFiltered(), but if UserLogService.findAll() is still annotated with @PreAuthorize("isAuthenticated()"), then any authenticated user (including USER role) can still call it and access the full user event log — which contains sensitive data (logins, authorization changes, etc.).

Please verify/confirm that UserLogService.findAll() has been restricted. If not, the fix would be:

// UserLogService.java
- `@PreAuthorize`("isAuthenticated()")
+ `@PreAuthorize`("hasRole('SYSADMIN')")
  public List<UserLogDTO> findAll() {

Minor — authenticateAsSysadmin() persists to the database

Each call to authenticateAsSysadmin() saves a new User row with a random UUID email. This is functionally fine, but creates test-DB noise. Since the sysadmin only needs to be in the SecurityContext for the assertion (not for a DB-level auth check), you could avoid the userRepository.save() and just set the SecurityContext directly:

private void authenticateAsSysadmin() {
    User sysadmin = new User();
    sysadmin.setId(-1L); // synthetic, not persisted
    sysadmin.setUserAuthorization(UserAuthorization.SYSADMIN);
    // ... etc
    authenticateUser(sysadmin); // without saving to repo
}

(Only applicable if findAll() doesn't hit the DB for the user itself.)

Minor — Commit message headlines

Both commits use the bare Fix: headline with no subject on the first line. Conventional commit format expects a concise description on the same line, e.g.:

  • Fix: restrict log service findFiltered to SYSADMIN
  • Fix: restrict log service findAll to SYSADMIN; extract log-page fragment

🧠 Learnings used
Learnt from: eeebbaandersson
Repo: ithsjava25/visa-case-management-system PR: 27
File: src/main/resources/templates/visa/details.html:237-244
Timestamp: 2026-04-14T12:40:29.108Z
Learning: In `visa-case-management-system`, the comment form in `src/main/resources/templates/visa/details.html` (around lines 237-244) currently submits to `/api/comments` with form fields `visaId`, `authorId`, and `content` (wrong field name). The intended fix is to replace the HTML form with JavaScript/fetch to POST JSON to the existing REST endpoint `/api/comments`. The correct JSON body field for the comment text is `text` (matching `CreateCommentDTO`), not `content`. This is a known deferred issue to be addressed in a future PR.

- Missing authorization check change on findAll in UserLogService
@Martin-E-Karlsson
Martin-E-Karlsson merged commit 6aa8c04 into main Apr 27, 2026
2 checks passed
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.

Visualize File Log and Comment Log in SysAdmin view

1 participant