Skip to content

Feature/frontend registry and caserecord - #36

Merged
JohanHiths merged 52 commits into
mainfrom
feature/frontend-registry-and-caserecord
Apr 23, 2026
Merged

Feature/frontend registry and caserecord#36
JohanHiths merged 52 commits into
mainfrom
feature/frontend-registry-and-caserecord

Conversation

@MartinStenhagen

@MartinStenhagen MartinStenhagen commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

resolves #28

Summary by CodeRabbit

  • New Features

    • Case management dashboard: registries, case record list/detail, create/update flows.
    • File uploads with automatic document numbering, unique document references and confidentiality levels.
    • Role-aware access controls: confidential files masked or hidden; downloads and deletes enforce permissions.
    • Admin UI to grant/revoke confidential-file access.
  • UI Improvements

    • Responsive case-management UI, new fragments and styles; HTMX-enabled upload/list/download/delete interactions and localized Swedish messages.

…enum. Updated existing tests to work with confidentiality
…Enforce confidentiality at download/delete boundaries, not only in the list DTO.
…agment-method to fix coderabbit feedback: Avoid rethrowing after handling upload/delete errors
…s, consistant use of enums and other improvements
                 th:attr="hx-post=@{/dashboard/case-management/registries}"
                 hx-target="#registry-panel"
                 hx-swap="innerHTML">
after coderabbit feedback

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 7

♻️ Duplicate comments (2)
src/main/java/backendlab/team4you/exceptions/ApiExceptionHandler.java (1)

193-204: ⚠️ Potential issue | 🟠 Major

Sanitize storage configuration errors before returning them.

Line 201 exposes the raw configuration exception message to API clients. Keep the detailed exception in the server log and return a generic message instead.

🛡️ Proposed fix
         return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                 .body(new ErrorResponseDto(
                         HttpStatus.INTERNAL_SERVER_ERROR.value(),
                         "internal server error",
-                        ex.getMessage(),
+                        "file storage is temporarily unavailable",
                         LocalDateTime.now()
                 ));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/backendlab/team4you/exceptions/ApiExceptionHandler.java` around
lines 193 - 204, The handler handleFileStorageConfiguration that catches
FileStorageConfigurationException currently returns ex.getMessage() to clients;
change it to return a generic message (e.g., "File storage configuration error"
or a user-friendly note) while preserving the full exception in the server log
via log.error("File storage configuration error", ex). Update the
ErrorResponseDto construction in handleFileStorageConfiguration to use the
generic message instead of ex.getMessage() so sensitive configuration details
are not exposed to API clients.
src/main/java/backendlab/team4you/casefile/CaseFile.java (1)

51-53: ⚠️ Potential issue | 🟠 Major

Prevent null confidentiality from failing open.

The DB column is non-null, but the entity still allows null; Line 136 then treats that state as non-confidential. Enforce the invariant in Java so in-memory access-control checks cannot expose confidential files before persistence catches the bad state.

🛡️ Proposed fix
 import jakarta.persistence.*;
 
 import java.time.LocalDateTime;
+import java.util.Objects;
@@
     `@Enumerated`(EnumType.STRING)
     `@Column`(name = "confidentiality_level", nullable = false, length = 50)
-    private ConfidentialityLevel confidentialityLevel;
+    private ConfidentialityLevel confidentialityLevel = ConfidentialityLevel.CONFIDENTIAL;
@@
     public void setConfidentialityLevel(ConfidentialityLevel confidentialityLevel) {
-        this.confidentialityLevel = confidentialityLevel;
+        this.confidentialityLevel = Objects.requireNonNull(confidentialityLevel, "confidentialityLevel");
     }
 
     public boolean isConfidential() {
+        if (confidentialityLevel == null) {
+            return true;
+        }
         return confidentialityLevel == ConfidentialityLevel.CONFIDENTIAL;
     }

Also applies to: 131-136

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

In `@src/main/java/backendlab/team4you/casefile/CaseFile.java` around lines 51 -
53, The ConfidentialityLevel field in CaseFile currently allows null in-memory
which can be treated as non-confidential; change the field to enforce non-null
by annotating it with `@NotNull` (javax.validation) and initializing it to the
most restrictive value (e.g., ConfidentialityLevel.CONFIDENTIAL) so new
instances never have a null confidentialityLevel; also update constructors and
the setConfidentialityLevel method to validate/require non-null to preserve the
invariant during object creation and mutation.
🧹 Nitpick comments (3)
src/main/java/backendlab/team4you/caserecord/CaseRecordService.java (1)

167-180: normalizeStatus is unused — drop it.

createCaseRecord and updateCaseRecord both accept CaseStatus directly (typed enum), and there's no remaining String status boundary in this service. This helper is never called and will quickly drift from the enum (OPEN/CLOSED hardcoded as strings). Remove it to avoid confusion.

Proposed removal
-    private String normalizeStatus(String status) {
-        if (status == null || status.isBlank()) {
-            throw new IllegalArgumentException("status is required");
-        }
-
-        String normalizedStatus = status.trim().toUpperCase();
-
-        if (!normalizedStatus.equals("OPEN")
-                && !normalizedStatus.equals("CLOSED")) {
-            throw new IllegalArgumentException("invalid status: " + status);
-        }
-
-        return normalizedStatus;
-    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/backendlab/team4you/caserecord/CaseRecordService.java` around
lines 167 - 180, Remove the unused normalizeStatus method from
CaseRecordService: delete the private String normalizeStatus(String status)
implementation and any related imports so the class relies on the CaseStatus
enum used by createCaseRecord and updateCaseRecord; confirm there are no
remaining call sites or string-based status handling in this service and run
tests to ensure compilation.
src/main/java/backendlab/team4you/casefile/CaseFileController.java (1)

58-87: Minor: downloadFile resolves the file twice.

caseFileService.getCaseFileForViewer(...) is invoked at line 64 to read metadata (content type, filename), and then caseFileService.downloadFile(caseRecordId, fileId, currentUser) runs getCaseFileForViewer again inside the streaming lambda — so every download does two findByIdAndCaseRecordId lookups plus two canViewFile checks. Consider either exposing a variant that takes the already-resolved CaseFile, or pulling just the s3Key onto caseFile here and calling s3Service.downloadFile(caseFile.getS3Key()) directly from the lambda.

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

In `@src/main/java/backendlab/team4you/casefile/CaseFileController.java` around
lines 58 - 87, The downloadFile controller currently calls
caseFileService.getCaseFileForViewer(...) to load metadata and then calls
caseFileService.downloadFile(...) inside the StreamingResponseBody which repeats
the same lookup and permission checks; change the implementation to reuse the
loaded CaseFile: after calling caseFileService.getCaseFileForViewer(...) extract
the s3Key (caseFile.getS3Key()) and use s3Service.downloadFile(s3Key) (or add a
caseFileService.downloadFile(CaseFile) overload) inside the lambda so the DB
lookup and canViewFile check run only once.
src/main/java/backendlab/team4you/exceptions/GlobalRestExceptionHandler.java (1)

39-52: Mapping every IllegalArgumentException to 400 is broad.

Grouping IllegalArgumentException with validation exceptions here means any internal programming bug that raises an IAE inside the casefile/caserecord flows (e.g., allocateNextCaseNumber on unreachable branches, unexpected enum coercion inside a service) will be reported to clients as 400 Bad Request with the raw ex.getMessage() leaked to the response body. That both hides real defects from monitoring and risks exposing implementation details.

Consider replacing IAE-based validation with a dedicated domain exception (e.g. InvalidRequestException) so genuine programmer errors still reach the catch-all and are logged.

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

In `@src/main/java/backendlab/team4you/exceptions/GlobalRestExceptionHandler.java`
around lines 39 - 52, The handler GlobalRestExceptionHandler.handleBadRequest is
too broad because it maps IllegalArgumentException to 400 and returns
ex.getMessage() to clients; instead remove IllegalArgumentException from the 400
handler and introduce a dedicated domain validation exception (e.g.
InvalidRequestException extends RuntimeException) for true client-side
validation errors, update service/code paths (e.g. allocateNextCaseNumber and
casefile/caserecord validation code) to throw InvalidRequestException where
input is invalid, change the handler to catch InvalidRequestException alongside
InvalidFileNameException and FileTooLargeException and keep returning sanitized
ex.getMessage(), and ensure IllegalArgumentException falls through to the global
catch-all so programming errors are logged and returned as 500s rather than
leaked as 400s.
🤖 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/backendlab/team4you/exceptions/ApiExceptionHandler.java`:
- Around line 206-215: Remove the duplicate AccessDeniedException handler from
ApiExceptionHandler: delete the method
handleAccessDenied(org.springframework.security.access.AccessDeniedException ex)
so the application uses the single, canonical response in
GlobalRestExceptionHandler; if you must keep a handler here, make it return the
exact same response structure and message as GlobalRestExceptionHandler instead
of ex.getMessage() to prevent advice-order dependent behavior.

In
`@src/main/java/backendlab/team4you/exceptions/GlobalRestExceptionHandler.java`:
- Around line 94-105: Add explicit exception handler methods in
GlobalRestExceptionHandler for MethodArgumentNotValidException,
HttpMessageNotReadableException, MissingServletRequestParameterException and
MethodArgumentTypeMismatchException that log the error and return
ResponseEntity<ErrorResponseDto> with HttpStatus.BAD_REQUEST (400) and a
suitable message; keep the existing handleUnexpected(Exception ex) as the
catch‑all fallback so framework 4xx exceptions (e.g., the
MethodArgumentTypeMismatchException thrown by CaseFileController.uploadFile's
`@RequestParam` ConfidentialityLevel binding) are not converted to 500.

In `@src/main/resources/db/migration/V18__case_file_changes.sql`:
- Around line 1-8: The ALTER TABLE statements in V18__case_file_changes.sql that
set document_number and document_reference to NOT NULL are redundant because
those columns were already backfilled and constrained in
V15__case_file_numbering.sql; remove the two ALTER COLUMN ... SET NOT NULL
statements for document_number and document_reference from
V18__case_file_changes.sql (or, if there was an intentional drop/re-add, add a
clear comment and a migration step that shows why they were dropped and re-added
and includes the backfill), leaving only the intended change to
case_record.assigned_user_id.

In `@src/main/resources/templates/fragments/case-management/case-file-list.html`:
- Around line 64-67: The HTMX delete button lacks the CSRF header and will be
rejected by Spring Security; update the button that has the hx-delete attribute
so it also sends the CSRF header by adding an hx-headers attribute populated
from the CSRF meta values (use the same pattern as check.html: read the _csrf
header name and _csrf token meta values and add a JSON headers object mapping
the header name to the token). Ensure the change affects the button with
hx-delete that targets the case-file panel and will allow
CaseFileViewController.deleteCaseFile(...) to receive a valid CSRF header.

In
`@src/main/resources/templates/fragments/case-management/case-record-detail.html`:
- Around line 47-50: Thymeleaf is comparing the enum instance to strings, so
change the th:selected checks to compare the enum's name(): update the select
options with th:selected="${caseRecord.status.name() == 'OPEN'}" and
th:selected="${caseRecord.status.name() == 'CLOSED'}" (or guard with
caseRecord.status != null if needed) for the options in the element with id
"update-case-status" so the current CaseStatus is selected correctly.

In `@src/test/java/backendlab/team4you/casefile/CaseFileControllerTest.java`:
- Around line 310-333: Rename the test method and its `@DisplayName` to reflect
the 413 expectation: change the method
uploadFile_shouldReturnBadRequest_whenFileIsTooLarge to
uploadFile_shouldReturnContentTooLarge_whenFileIsTooLarge (or similar) and
update the `@DisplayName` from "uploadFile should return bad request when file is
too large" to something like "uploadFile should return 413 Content Too Large
when file is too large" so the method name and display name match the
isContentTooLarge()/413 assertions in the test.

In `@src/test/java/backendlab/team4you/casefile/CaseFileServiceTest.java`:
- Around line 487-501: The test method
uploadFile_shouldThrowFileTooLargeException_whenFileTooLarge in
CaseFileServiceTest is missing the `@Test` annotation so JUnit won't run it; add
the org.junit.jupiter.api.Test annotation above this method (in addition to the
existing `@DisplayName`) so the test framework executes the oversized-file
assertion for caseFileService.uploadFile.

---

Duplicate comments:
In `@src/main/java/backendlab/team4you/casefile/CaseFile.java`:
- Around line 51-53: The ConfidentialityLevel field in CaseFile currently allows
null in-memory which can be treated as non-confidential; change the field to
enforce non-null by annotating it with `@NotNull` (javax.validation) and
initializing it to the most restrictive value (e.g.,
ConfidentialityLevel.CONFIDENTIAL) so new instances never have a null
confidentialityLevel; also update constructors and the setConfidentialityLevel
method to validate/require non-null to preserve the invariant during object
creation and mutation.

In `@src/main/java/backendlab/team4you/exceptions/ApiExceptionHandler.java`:
- Around line 193-204: The handler handleFileStorageConfiguration that catches
FileStorageConfigurationException currently returns ex.getMessage() to clients;
change it to return a generic message (e.g., "File storage configuration error"
or a user-friendly note) while preserving the full exception in the server log
via log.error("File storage configuration error", ex). Update the
ErrorResponseDto construction in handleFileStorageConfiguration to use the
generic message instead of ex.getMessage() so sensitive configuration details
are not exposed to API clients.

---

Nitpick comments:
In `@src/main/java/backendlab/team4you/casefile/CaseFileController.java`:
- Around line 58-87: The downloadFile controller currently calls
caseFileService.getCaseFileForViewer(...) to load metadata and then calls
caseFileService.downloadFile(...) inside the StreamingResponseBody which repeats
the same lookup and permission checks; change the implementation to reuse the
loaded CaseFile: after calling caseFileService.getCaseFileForViewer(...) extract
the s3Key (caseFile.getS3Key()) and use s3Service.downloadFile(s3Key) (or add a
caseFileService.downloadFile(CaseFile) overload) inside the lambda so the DB
lookup and canViewFile check run only once.

In `@src/main/java/backendlab/team4you/caserecord/CaseRecordService.java`:
- Around line 167-180: Remove the unused normalizeStatus method from
CaseRecordService: delete the private String normalizeStatus(String status)
implementation and any related imports so the class relies on the CaseStatus
enum used by createCaseRecord and updateCaseRecord; confirm there are no
remaining call sites or string-based status handling in this service and run
tests to ensure compilation.

In
`@src/main/java/backendlab/team4you/exceptions/GlobalRestExceptionHandler.java`:
- Around line 39-52: The handler GlobalRestExceptionHandler.handleBadRequest is
too broad because it maps IllegalArgumentException to 400 and returns
ex.getMessage() to clients; instead remove IllegalArgumentException from the 400
handler and introduce a dedicated domain validation exception (e.g.
InvalidRequestException extends RuntimeException) for true client-side
validation errors, update service/code paths (e.g. allocateNextCaseNumber and
casefile/caserecord validation code) to throw InvalidRequestException where
input is invalid, change the handler to catch InvalidRequestException alongside
InvalidFileNameException and FileTooLargeException and keep returning sanitized
ex.getMessage(), and ensure IllegalArgumentException falls through to the global
catch-all so programming errors are logged and returned as 500s rather than
leaked as 400s.
🪄 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: 25fdf703-cf8d-4814-bb06-86d8fc708720

📥 Commits

Reviewing files that changed from the base of the PR and between 9d426e3 and e847dbe.

📒 Files selected for processing (40)
  • src/main/java/backendlab/team4you/Team4youApplication.java
  • src/main/java/backendlab/team4you/casefile/CaseFile.java
  • src/main/java/backendlab/team4you/casefile/CaseFileController.java
  • src/main/java/backendlab/team4you/casefile/CaseFileRepository.java
  • src/main/java/backendlab/team4you/casefile/CaseFileResponseDto.java
  • src/main/java/backendlab/team4you/casefile/CaseFileService.java
  • src/main/java/backendlab/team4you/casefile/access/CaseFileAccessService.java
  • src/main/java/backendlab/team4you/casefile/ui/CaseFileViewController.java
  • src/main/java/backendlab/team4you/casefile/ui/CaseManagementViewController.java
  • src/main/java/backendlab/team4you/casefile/ui/CaseRecordViewController.java
  • src/main/java/backendlab/team4you/caserecord/CaseRecord.java
  • src/main/java/backendlab/team4you/caserecord/CaseRecordRepository.java
  • src/main/java/backendlab/team4you/caserecord/CaseRecordRequestDto.java
  • src/main/java/backendlab/team4you/caserecord/CaseRecordResponseDto.java
  • src/main/java/backendlab/team4you/caserecord/CaseRecordService.java
  • src/main/java/backendlab/team4you/caserecord/CaseStatus.java
  • src/main/java/backendlab/team4you/common/ConfidentialityLevel.java
  • src/main/java/backendlab/team4you/config/SecurityConfig.java
  • src/main/java/backendlab/team4you/controller/SignupController.java
  • src/main/java/backendlab/team4you/exceptions/ApiExceptionHandler.java
  • src/main/java/backendlab/team4you/exceptions/FileTooLargeException.java
  • src/main/java/backendlab/team4you/exceptions/GlobalExceptionHandler.java
  • src/main/java/backendlab/team4you/exceptions/GlobalRestExceptionHandler.java
  • src/main/java/backendlab/team4you/exceptions/GlobalViewExceptionHandler.java
  • src/main/java/backendlab/team4you/user/UserService.java
  • src/main/resources/db/migration/V18__case_file_changes.sql
  • src/main/resources/templates/dashboard-layout.html
  • src/main/resources/templates/dashboard/case-management.html
  • src/main/resources/templates/fragments/admin-sidenav.html
  • src/main/resources/templates/fragments/case-management/case-file-list.html
  • src/main/resources/templates/fragments/case-management/case-record-detail.html
  • src/main/resources/templates/fragments/case-management/page.html
  • src/main/resources/templates/fragments/case-management/registry-list.html
  • src/test/java/backendlab/team4you/casefile/CaseFileControllerTest.java
  • src/test/java/backendlab/team4you/casefile/CaseFileServiceTest.java
  • src/test/java/backendlab/team4you/casefile/access/CaseFileAccessServiceTest.java
  • src/test/java/backendlab/team4you/casefile/ui/CaseFileViewControllerTest.java
  • src/test/java/backendlab/team4you/caserecord/CaseRecordControllerTest.java
  • src/test/java/backendlab/team4you/caserecord/CaseRecordServiceTest.java
  • src/test/java/backendlab/team4you/caserecord/CaseRecordTest.java
💤 Files with no reviewable changes (1)
  • src/main/java/backendlab/team4you/exceptions/GlobalExceptionHandler.java
✅ Files skipped from review due to trivial changes (6)
  • src/main/resources/templates/fragments/admin-sidenav.html
  • src/main/java/backendlab/team4you/common/ConfidentialityLevel.java
  • src/main/java/backendlab/team4you/caserecord/CaseStatus.java
  • src/main/resources/templates/dashboard/case-management.html
  • src/main/resources/templates/dashboard-layout.html
  • src/main/java/backendlab/team4you/Team4youApplication.java
🚧 Files skipped from review as they are similar to previous changes (10)
  • src/main/java/backendlab/team4you/exceptions/FileTooLargeException.java
  • src/main/java/backendlab/team4you/config/SecurityConfig.java
  • src/main/java/backendlab/team4you/casefile/CaseFileResponseDto.java
  • src/main/java/backendlab/team4you/caserecord/CaseRecordRepository.java
  • src/main/java/backendlab/team4you/casefile/CaseFileRepository.java
  • src/test/java/backendlab/team4you/casefile/access/CaseFileAccessServiceTest.java
  • src/main/java/backendlab/team4you/caserecord/CaseRecord.java
  • src/main/java/backendlab/team4you/casefile/access/CaseFileAccessService.java
  • src/test/java/backendlab/team4you/casefile/ui/CaseFileViewControllerTest.java
  • src/main/java/backendlab/team4you/casefile/ui/CaseRecordViewController.java

Comment thread src/main/java/backendlab/team4you/exceptions/ApiExceptionHandler.java Outdated
Comment thread src/main/resources/db/migration/V18__case_file_changes.sql Outdated
Comment thread src/test/java/backendlab/team4you/casefile/CaseFileServiceTest.java

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/test/java/backendlab/team4you/casefile/CaseFileServiceTest.java (1)

86-98: Assert the persisted confidentiality level on upload.

This success path now passes ConfidentialityLevel.OPEN, but it never verifies that the returned CaseFile carries the selected level. Add the assertion so regressions in confidentiality persistence are caught.

🧪 Proposed test assertion
         assertThat(result.getDocumentNumber()).isEqualTo(1);
         assertThat(result.getDocumentReference()).isEqualTo("KS26-1-1");
+        assertThat(result.getConfidentialityLevel()).isEqualTo(ConfidentialityLevel.OPEN);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/test/java/backendlab/team4you/casefile/CaseFileServiceTest.java` around
lines 86 - 98, The test calls caseFileService.uploadFile(1L, file,
ConfidentialityLevel.OPEN, actor) but never asserts the persisted
confidentiality; update the assertion block for the CaseFile result to include
an assertion that the returned object's confidentiality accessor (e.g.,
result.getConfidentialityLevel() or the project's actual getter) is equal to
ConfidentialityLevel.OPEN so the test verifies confidentiality is persisted on
upload.
src/test/java/backendlab/team4you/casefile/CaseFileControllerTest.java (1)

75-85: Assert confidentialityLevel in the upload response.

CaseFileResponseDto exposes this new field, but the controller test does not verify it is serialized. This is a small, high-value assertion for the confidentiality feature.

🧪 Proposed test assertion
                 .andExpect(jsonPath("$.size").value(123))
                 .andExpect(jsonPath("$.documentNumber").value(1))
-                .andExpect(jsonPath("$.documentReference").value("KS26-1-1"));
+                .andExpect(jsonPath("$.documentReference").value("KS26-1-1"))
+                .andExpect(jsonPath("$.confidentialityLevel").value("OPEN"));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/test/java/backendlab/team4you/casefile/CaseFileControllerTest.java`
around lines 75 - 85, The test in CaseFileControllerTest performing the
multipart upload doesn't assert the new confidentialityLevel field from
CaseFileResponseDto; add an assertion to the mockMvc expectation chain to verify
the response JSON contains confidentialityLevel with the expected value (e.g.
add an andExpect(jsonPath("$.confidentialityLevel").value("OPEN")) to the
multipart("/api/cases/{caseRecordId}/files", 1L) test). Ensure the assertion is
added alongside the other jsonPath checks after the perform call so the
controller's serialization of CaseFileResponseDto.confidentialityLevel is
verified.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/test/java/backendlab/team4you/casefile/CaseFileControllerTest.java`:
- Around line 75-85: The test in CaseFileControllerTest performing the multipart
upload doesn't assert the new confidentialityLevel field from
CaseFileResponseDto; add an assertion to the mockMvc expectation chain to verify
the response JSON contains confidentialityLevel with the expected value (e.g.
add an andExpect(jsonPath("$.confidentialityLevel").value("OPEN")) to the
multipart("/api/cases/{caseRecordId}/files", 1L) test). Ensure the assertion is
added alongside the other jsonPath checks after the perform call so the
controller's serialization of CaseFileResponseDto.confidentialityLevel is
verified.

In `@src/test/java/backendlab/team4you/casefile/CaseFileServiceTest.java`:
- Around line 86-98: The test calls caseFileService.uploadFile(1L, file,
ConfidentialityLevel.OPEN, actor) but never asserts the persisted
confidentiality; update the assertion block for the CaseFile result to include
an assertion that the returned object's confidentiality accessor (e.g.,
result.getConfidentialityLevel() or the project's actual getter) is equal to
ConfidentialityLevel.OPEN so the test verifies confidentiality is persisted on
upload.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9225dafb-677e-4eb8-838d-aa5c883e60d7

📥 Commits

Reviewing files that changed from the base of the PR and between e847dbe and 7f08b5e.

📒 Files selected for processing (10)
  • src/main/java/backendlab/team4you/exceptions/ApiExceptionHandler.java
  • src/main/java/backendlab/team4you/exceptions/GlobalRestExceptionHandler.java
  • src/main/resources/db/migration/V18__case_file_changes.sql
  • src/main/resources/templates/fragments/case-management/case-file-list.html
  • src/main/resources/templates/fragments/case-management/case-record-detail.html
  • src/test/java/backendlab/team4you/UserControllerTest.java
  • src/test/java/backendlab/team4you/casefile/CaseFileControllerTest.java
  • src/test/java/backendlab/team4you/casefile/CaseFileServiceTest.java
  • src/test/java/backendlab/team4you/caserecord/CaseRecordControllerTest.java
  • src/test/java/backendlab/team4you/registry/RegistryControllerTest.java
💤 Files with no reviewable changes (1)
  • src/main/java/backendlab/team4you/exceptions/ApiExceptionHandler.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/test/java/backendlab/team4you/caserecord/CaseRecordControllerTest.java

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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/resources/templates/fragments/case-management/case-record-list.html`:
- Around line 62-68: The select with id "confidentiality-level" and name
"confidentialityLevel" defaults to "OPEN" so required doesn't force a deliberate
choice; add a sentinel option with an empty value (e.g. value="") that is
selected by default and disabled (a prompt like "välj sekretessnivå") so the
browser will require the user to pick one of the real options before submit, or
alternatively remove the default selection so no real option is preselected.
- Around line 44-47: The label "ägare" is not associated with the input and
using disabled removes the value from focus/assistive flows; update the input
that renders th:value="${currentUserDisplayName}" to include a unique id (e.g.,
id="ownerDisplay") and change the label to use for="ownerDisplay", and replace
the disabled attribute with readonly so the owner value remains non-editable but
focusable/accessible to assistive tech.
🪄 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: deb38c03-bf55-4532-9a44-2b474a60fbc1

📥 Commits

Reviewing files that changed from the base of the PR and between 7f08b5e and a573c9a.

📒 Files selected for processing (2)
  • src/main/resources/templates/fragments/case-management/case-record-list.html
  • src/main/resources/templates/fragments/case-management/registry-list.html

Comment thread src/main/resources/templates/fragments/case-management/case-record-list.html Outdated
…ly value and Force an explicit confidentiality choice before submit.
@JohanHiths
JohanHiths merged commit 23480bb into main Apr 23, 2026
2 checks passed
@MartinStenhagen
MartinStenhagen deleted the feature/frontend-registry-and-caserecord branch April 24, 2026 15:46
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.

Frontend registry and caserecord + File confidentiality

2 participants