Skip to content

Employee entity etc#25

Merged
LinusWestling merged 2 commits intomainfrom
feature/employee
Mar 31, 2026
Merged

Employee entity etc#25
LinusWestling merged 2 commits intomainfrom
feature/employee

Conversation

@LinusWestling
Copy link
Copy Markdown
Collaborator

@LinusWestling LinusWestling commented Mar 31, 2026

Summary by CodeRabbit

  • New Features
    • Employee management: create, view, and list employees.
    • Role support expanded (Manager, Doctor, Nurse, Patient) for clearer access levels.
    • Role-based access control for case visibility and operations.
    • Case assignment endpoint: assign owner, handler, and other participants.
    • Patient selection is now required when creating a case.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 31, 2026

📝 Walkthrough

Walkthrough

Role-based authorization was added across case workflows by threading an Actor through controllers and services. New employee domain (entity, repo, DTOs, mapper, service, controller) and case assignment fields/endpoints were introduced; controllers now obtain current user via HeaderCurrentUserAdapter.

Changes

Cohort / File(s) Summary
Case service & controllers
src/main/java/org/example/projektarendehantering/application/service/CaseService.java, src/main/java/org/example/projektarendehantering/presentation/rest/CaseController.java, src/main/java/org/example/projektarendehantering/presentation/web/UiController.java, src/main/java/org/example/projektarendehantering/presentation/rest/PatientController.java
Thread Actor (current user) through case APIs; method signatures changed to accept Actor; added role-based checks (requireCanRead/canCreate), role-scoped getAllCases/getCasesForPatient, new assignUsers transactional method, and controller endpoint PUT /api/cases/{id}/assignments. Controllers now inject HeaderCurrentUserAdapter.
Employee domain (persistence → service → API)
src/main/java/org/example/projektarendehantering/infrastructure/persistence/EmployeeEntity.java, src/main/java/org/example/projektarendehantering/infrastructure/persistence/EmployeeRepository.java, src/main/java/org/example/projektarendehantering/application/service/EmployeeMapper.java, src/main/java/org/example/projektarendehantering/application/service/EmployeeService.java, src/main/java/org/example/projektarendehantering/presentation/rest/EmployeeController.java, src/main/java/org/example/projektarendehantering/presentation/dto/EmployeeCreateDTO.java, src/main/java/org/example/projektarendehantering/presentation/dto/EmployeeDTO.java
Added EmployeeEntity + JPA repo; mapper and service with Actor-based authorization; new REST controller and DTOs for create/get/list employees.
Case model & repo extensions
src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseEntity.java, src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseRepository.java, src/main/java/org/example/projektarendehantering/presentation/dto/CaseAssignmentDTO.java
Added handlerId and otherId fields to CaseEntity; repository gained findAllByOwnerId, findAllByHandlerId, findAllByOtherId; new CaseAssignmentDTO for assignment updates.
Role enum & forms
src/main/java/org/example/projektarendehantering/common/Role.java, src/main/java/org/example/projektarendehantering/presentation/dto/CreateCaseForm.java
Added preferred roles MANAGER, DOCTOR, NURSE, PATIENT (legacy constants retained). CreateCaseForm now requires patientId (@NotNull).

Sequence Diagram

sequenceDiagram
    actor Client
    participant CaseController
    participant HeaderCurrentUserAdapter
    participant CaseService
    participant EmployeeRepository
    participant CaseRepository
    participant Database

    Client->>CaseController: PUT /api/cases/{id}/assignments (body)
    CaseController->>HeaderCurrentUserAdapter: currentUser()
    HeaderCurrentUserAdapter-->>CaseController: Actor
    CaseController->>CaseService: assignUsers(Actor, caseId, dto)
    CaseService->>CaseService: authorize manager/doctor (require/deny)
    alt Doctor acting on non-owned case
        CaseService-->>Client: throw NotAuthorizedException
    else Allowed
        CaseService->>EmployeeRepository: findById(owner/handler/other) (validate roles)
        EmployeeRepository->>Database: query
        Database-->>EmployeeRepository: employee rows
        EmployeeRepository-->>CaseService: employee entities
        CaseService->>CaseRepository: findById(caseId) / save(updated case)
        CaseRepository->>Database: query/update
        Database-->>CaseRepository: entity/result
        CaseRepository-->>CaseService: saved CaseEntity
        CaseService->>CaseService: map to CaseDTO
        CaseService-->>CaseController: CaseDTO
        CaseController-->>Client: 200 OK with CaseDTO
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Poem

🐰 I hopped in code with nimble paws,

Roles and owners, new-made laws.
Doctors, nurses, managers, too—
Cases assigned, the team in view.
A carrot cheer for every new review!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 'Employee entity etc' is vague and uses non-descriptive language ('etc') that doesn't clearly convey the scope or main purpose of the changes. Revise the title to be more descriptive and specific, such as 'Add employee management with role-based authorization' or 'Implement employee service and role-based case assignments'.
✅ 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/employee

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

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/projektarendehantering/presentation/web/UiController.java (1)

50-53: ⚠️ Potential issue | 🟠 Major

Repopulate patients when re-rendering the form.

On validation failure we return cases/new without the patients attribute added on Line 46, so the retry view loses its patient options and can no longer submit correctly.

Suggested fix
-    public String createCase(`@Valid` `@ModelAttribute`("createCaseForm") CreateCaseForm form, BindingResult result) {
+    public String createCase(`@Valid` `@ModelAttribute`("createCaseForm") CreateCaseForm form,
+                             BindingResult result,
+                             Model model) {
         if (result.hasErrors()) {
+            model.addAttribute("patients", patientService.getAllPatients());
             return "cases/new";
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/org/example/projektarendehantering/presentation/web/UiController.java`
around lines 50 - 53, The POST handler createCase currently returns "cases/new"
on validation errors without repopulating the "patients" model attribute,
causing the retry form to miss patient options; update createCase (signature and
body) to accept the Model (or use existing helper) and, when result.hasErrors()
is true, add the same "patients" attribute used for the GET/new view (e.g., via
patientService.findAll() or the existing populate method) before returning
"cases/new" so the form has its patient options on redisplay.
🧹 Nitpick comments (2)
src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseEntity.java (1)

19-20: Clarify otherId semantics to reduce RBAC drift.

otherId is very generic for an authorization-critical field. Consider renaming (or adding Javadoc) to express the exact actor relationship used in access checks.

Also applies to: 50-51

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

In
`@src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseEntity.java`
around lines 19 - 20, The field otherId on CaseEntity is too generic for
authorization logic; update CaseEntity to either rename otherId to a clear,
specific identifier (e.g., reporterId, ownerId, relatedActorId) that matches its
RBAC role or add Javadoc on otherId and handlerId explaining the exact actor
relationship used in access checks (who it represents, when it is populated, and
how it is used in permission rules); ensure all references/usages (access
checks, DTO mapping, persistence queries) are updated to the new name or consult
the Javadoc so authorization code remains unambiguous.
src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseRepository.java (1)

10-12: Add indexes for the new role-filter query columns.

These repository methods will trend hot as case volume grows. Ensure DB indexes exist for owner_id, handler_id, and other_id to avoid full-table scans.

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

In
`@src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseRepository.java`
around lines 10 - 12, The repository exposes hot lookup methods
(findAllByOwnerId, findAllByHandlerId, findAllByOtherId) but the DB schema lacks
indexes on the backing columns (owner_id, handler_id, other_id); add B-tree
indexes for these columns in your migration SQL (or JPA/Hibernate schema
changes) so queries using CaseRepository.findAllByOwnerId, findAllByHandlerId
and findAllByOtherId use the indexes and avoid full table scans—create indexes
named clearly (e.g., idx_case_owner_id, idx_case_handler_id, idx_case_other_id)
and include them in your migration/versioning system so they are applied
reliably.
🤖 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/projektarendehantering/application/service/CaseService.java`:
- Around line 87-90: The patient branch is comparing actor.userId() to otherId,
which misses cases where createCase() stores the patient relation on the Case
entity; update the patient-access logic to use the Case's patient identifier
instead of otherId. Specifically, replace usage of
caseRepository.findAllByOtherId(...) / otherId checks with a repository method
or in-stream filter that compares actor.userId() to the Case's patient id (e.g.,
Case.getPatientId() or Case.getPatient().getId()), and make the same change for
the analogous block referenced at 119-124 so patients see cases tied via the
stored patient relation.
- Around line 113-115: The code in CaseService that blindly copies
dto.getOwnerId()/getHandlerId()/getOtherId() to entity must validate each UUID
before setting it: for each non-null dto ID, query the appropriate
repository/service (e.g., PrincipalRepository/UserRepository or the
domain-specific repo used elsewhere in CaseService) to ensure the record exists
and has the expected role/type, and if not throw a 4xx error (e.g.,
BadRequestException/IllegalArgumentException) with a clear message; only call
entity.setOwnerId(...)/setHandlerId(...)/setOtherId(...) after the
existence-and-role checks pass so you never persist nonexistent or wrong-type
principals.
- Around line 104-115: The assignUsers method currently lets any doctor modify
unowned cases or overwrite owner/handler/other fields; restrict doctor
permissions so only managers can set or change ownerId, and doctors may only
modify handlerId and otherId on cases they already own. Concretely: replace the
current doctor check with a guard that if isDoctor(actor) then require
entity.getOwnerId() != null && entity.getOwnerId().equals(actor.userId());
additionally, when isDoctor(actor) and dto.getOwnerId() != null (or any attempt
to change ownerId), reject with NotAuthorizedException (or ignore ownerId
change) so only isManager(actor) can set entity.setOwnerId(...); allow doctors
to update entity.setHandlerId(...) and entity.setOtherId(...) only when they are
the current owner.

In
`@src/main/java/org/example/projektarendehantering/application/service/EmployeeService.java`:
- Around line 27-44: The service methods createEmployee, getEmployee, and
getAllEmployees lack RBAC checks and must be made actor-aware: change the
signatures (or add overloads) to accept the current actor/principal (or fetch it
from a SecurityContext) and enforce permission checks inside EmployeeService
(e.g., verify actor has ROLE_HR or a specific permission before proceeding) when
invoked from EmployeeController; update EmployeeController to pass the current
actor to EmployeeService (mirroring how case endpoints pass the actor) and
ensure repository calls (employeeRepository.save, findById, findAll) only run
after the authorization check succeeds.

---

Outside diff comments:
In
`@src/main/java/org/example/projektarendehantering/presentation/web/UiController.java`:
- Around line 50-53: The POST handler createCase currently returns "cases/new"
on validation errors without repopulating the "patients" model attribute,
causing the retry form to miss patient options; update createCase (signature and
body) to accept the Model (or use existing helper) and, when result.hasErrors()
is true, add the same "patients" attribute used for the GET/new view (e.g., via
patientService.findAll() or the existing populate method) before returning
"cases/new" so the form has its patient options on redisplay.

---

Nitpick comments:
In
`@src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseEntity.java`:
- Around line 19-20: The field otherId on CaseEntity is too generic for
authorization logic; update CaseEntity to either rename otherId to a clear,
specific identifier (e.g., reporterId, ownerId, relatedActorId) that matches its
RBAC role or add Javadoc on otherId and handlerId explaining the exact actor
relationship used in access checks (who it represents, when it is populated, and
how it is used in permission rules); ensure all references/usages (access
checks, DTO mapping, persistence queries) are updated to the new name or consult
the Javadoc so authorization code remains unambiguous.

In
`@src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseRepository.java`:
- Around line 10-12: The repository exposes hot lookup methods
(findAllByOwnerId, findAllByHandlerId, findAllByOtherId) but the DB schema lacks
indexes on the backing columns (owner_id, handler_id, other_id); add B-tree
indexes for these columns in your migration SQL (or JPA/Hibernate schema
changes) so queries using CaseRepository.findAllByOwnerId, findAllByHandlerId
and findAllByOtherId use the indexes and avoid full table scans—create indexes
named clearly (e.g., idx_case_owner_id, idx_case_handler_id, idx_case_other_id)
and include them in your migration/versioning system so they are applied
reliably.
🪄 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: 4c74ac74-7bc2-43e8-af2a-574fe423dbfe

📥 Commits

Reviewing files that changed from the base of the PR and between 13c3794 and 69709df.

📒 Files selected for processing (16)
  • src/main/java/org/example/projektarendehantering/application/service/CaseService.java
  • src/main/java/org/example/projektarendehantering/application/service/EmployeeMapper.java
  • src/main/java/org/example/projektarendehantering/application/service/EmployeeService.java
  • src/main/java/org/example/projektarendehantering/common/Role.java
  • src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseEntity.java
  • src/main/java/org/example/projektarendehantering/infrastructure/persistence/CaseRepository.java
  • src/main/java/org/example/projektarendehantering/infrastructure/persistence/EmployeeEntity.java
  • src/main/java/org/example/projektarendehantering/infrastructure/persistence/EmployeeRepository.java
  • src/main/java/org/example/projektarendehantering/presentation/dto/CaseAssignmentDTO.java
  • src/main/java/org/example/projektarendehantering/presentation/dto/CreateCaseForm.java
  • src/main/java/org/example/projektarendehantering/presentation/dto/EmployeeCreateDTO.java
  • src/main/java/org/example/projektarendehantering/presentation/dto/EmployeeDTO.java
  • src/main/java/org/example/projektarendehantering/presentation/rest/CaseController.java
  • src/main/java/org/example/projektarendehantering/presentation/rest/EmployeeController.java
  • src/main/java/org/example/projektarendehantering/presentation/rest/PatientController.java
  • src/main/java/org/example/projektarendehantering/presentation/web/UiController.java

Comment on lines +27 to +44
@Transactional
public EmployeeDTO createEmployee(EmployeeCreateDTO dto) {
EmployeeEntity entity = employeeMapper.toEntity(dto);
entity.setId(UUID.randomUUID());
entity.setCreatedAt(Instant.now());
return employeeMapper.toDTO(employeeRepository.save(entity));
}

@Transactional(readOnly = true)
public Optional<EmployeeDTO> getEmployee(UUID id) {
return employeeRepository.findById(id).map(employeeMapper::toDTO);
}

@Transactional(readOnly = true)
public List<EmployeeDTO> getAllEmployees() {
return employeeRepository.findAll().stream()
.map(employeeMapper::toDTO)
.collect(Collectors.toList());
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 | 🔴 Critical

Add RBAC to the employee service before exposing it publicly.

These methods are the only new service surface in this PR that is not actor-aware. Combined with src/main/java/org/example/projektarendehantering/presentation/rest/EmployeeController.java:23-37, any authenticated caller reaching the controller can create employees or read the full employee directory, which is a privilege escalation.

Suggested direction
+import org.example.projektarendehantering.common.Actor;
+import org.example.projektarendehantering.common.NotAuthorizedException;
+import org.example.projektarendehantering.common.Role;
+
 `@Service`
 public class EmployeeService {
@@
     `@Transactional`
-    public EmployeeDTO createEmployee(EmployeeCreateDTO dto) {
+    public EmployeeDTO createEmployee(Actor actor, EmployeeCreateDTO dto) {
+        requireManager(actor);
         EmployeeEntity entity = employeeMapper.toEntity(dto);
         entity.setId(UUID.randomUUID());
         entity.setCreatedAt(Instant.now());
         return employeeMapper.toDTO(employeeRepository.save(entity));
     }
@@
     `@Transactional`(readOnly = true)
-    public Optional<EmployeeDTO> getEmployee(UUID id) {
+    public Optional<EmployeeDTO> getEmployee(Actor actor, UUID id) {
+        requireManager(actor);
         return employeeRepository.findById(id).map(employeeMapper::toDTO);
     }
@@
     `@Transactional`(readOnly = true)
-    public List<EmployeeDTO> getAllEmployees() {
+    public List<EmployeeDTO> getAllEmployees(Actor actor) {
+        requireManager(actor);
         return employeeRepository.findAll().stream()
                 .map(employeeMapper::toDTO)
                 .collect(Collectors.toList());
     }
+
+    private void requireManager(Actor actor) {
+        if (actor.role() != Role.MANAGER && actor.role() != Role.ADMIN) {
+            throw new NotAuthorizedException("Not allowed to manage employees");
+        }
+    }
 }

EmployeeController then needs to pass the current actor the same way the case endpoints do.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Transactional
public EmployeeDTO createEmployee(EmployeeCreateDTO dto) {
EmployeeEntity entity = employeeMapper.toEntity(dto);
entity.setId(UUID.randomUUID());
entity.setCreatedAt(Instant.now());
return employeeMapper.toDTO(employeeRepository.save(entity));
}
@Transactional(readOnly = true)
public Optional<EmployeeDTO> getEmployee(UUID id) {
return employeeRepository.findById(id).map(employeeMapper::toDTO);
}
@Transactional(readOnly = true)
public List<EmployeeDTO> getAllEmployees() {
return employeeRepository.findAll().stream()
.map(employeeMapper::toDTO)
.collect(Collectors.toList());
import org.example.projektarendehantering.common.Actor;
import org.example.projektarendehantering.common.NotAuthorizedException;
import org.example.projektarendehantering.common.Role;
`@Transactional`
public EmployeeDTO createEmployee(Actor actor, EmployeeCreateDTO dto) {
requireManager(actor);
EmployeeEntity entity = employeeMapper.toEntity(dto);
entity.setId(UUID.randomUUID());
entity.setCreatedAt(Instant.now());
return employeeMapper.toDTO(employeeRepository.save(entity));
}
`@Transactional`(readOnly = true)
public Optional<EmployeeDTO> getEmployee(Actor actor, UUID id) {
requireManager(actor);
return employeeRepository.findById(id).map(employeeMapper::toDTO);
}
`@Transactional`(readOnly = true)
public List<EmployeeDTO> getAllEmployees(Actor actor) {
requireManager(actor);
return employeeRepository.findAll().stream()
.map(employeeMapper::toDTO)
.collect(Collectors.toList());
}
private void requireManager(Actor actor) {
if (actor.role() != Role.MANAGER && actor.role() != Role.ADMIN) {
throw new NotAuthorizedException("Not allowed to manage employees");
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/org/example/projektarendehantering/application/service/EmployeeService.java`
around lines 27 - 44, The service methods createEmployee, getEmployee, and
getAllEmployees lack RBAC checks and must be made actor-aware: change the
signatures (or add overloads) to accept the current actor/principal (or fetch it
from a SecurityContext) and enforce permission checks inside EmployeeService
(e.g., verify actor has ROLE_HR or a specific permission before proceeding) when
invoked from EmployeeController; update EmployeeController to pass the current
actor to EmployeeService (mirroring how case endpoints pass the actor) and
ensure repository calls (employeeRepository.save, findById, findAll) only run
after the authorization check succeeds.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/main/java/org/example/projektarendehantering/application/service/EmployeeService.java (1)

45-51: Consider adding pagination for scalability.

findAll() loads all employees into memory. This works for small datasets but can cause performance issues as the employee count grows. Consider adding pagination support.

♻️ Suggested approach with pagination
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;

 `@Transactional`(readOnly = true)
-public List<EmployeeDTO> getAllEmployees(Actor actor) {
+public Page<EmployeeDTO> getAllEmployees(Actor actor, Pageable pageable) {
     requireCanManageEmployees(actor);
-    return employeeRepository.findAll().stream()
-            .map(employeeMapper::toDTO)
-            .collect(Collectors.toList());
+    return employeeRepository.findAll(pageable)
+            .map(employeeMapper::toDTO);
 }

This requires EmployeeRepository to extend PagingAndSortingRepository or JpaRepository (which it likely already does).

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

In
`@src/main/java/org/example/projektarendehantering/application/service/EmployeeService.java`
around lines 45 - 51, The getAllEmployees method currently uses
employeeRepository.findAll(), which loads all rows into memory; change it to
accept pagination parameters (e.g., PageRequest) and use
employeeRepository.findAll(Pageable) to return a Page<EmployeeDTO> (or a
paginated DTO list) by mapping Page.getContent() via employeeMapper::toDTO, and
update method signature and callers accordingly; ensure EmployeeRepository
extends JpaRepository/PagingAndSortingRepository so findAll(Pageable) is
available and add sensible defaults (page, size, sort) and validation for those
parameters in getAllEmployees.
src/main/java/org/example/projektarendehantering/application/service/CaseService.java (1)

110-116: Avoid using peek() for authorization side effects.

peek() is intended for debugging and its use for critical control flow like authorization is discouraged by the Java documentation. While it functions correctly here with collect(), this pattern is fragile and non-idiomatic.

♻️ Suggested refactor using explicit iteration
 `@Transactional`(readOnly = true)
 public List<CaseDTO> getCasesForPatient(Actor actor, UUID patientId) {
-    return caseRepository.findAllByPatient_Id(patientId).stream()
-            .peek(entity -> requireCanRead(actor, entity))
-            .map(caseMapper::toDTO)
-            .collect(Collectors.toList());
+    List<CaseEntity> entities = caseRepository.findAllByPatient_Id(patientId);
+    for (CaseEntity entity : entities) {
+        requireCanRead(actor, entity);
+    }
+    return entities.stream()
+            .map(caseMapper::toDTO)
+            .collect(Collectors.toList());
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/org/example/projektarendehantering/application/service/CaseService.java`
around lines 110 - 116, The getCasesForPatient method uses Stream.peek to
perform authorization (requireCanRead) which is a misuse of peek; instead,
retrieve the List from caseRepository.findAllByPatient_Id(patientId), iterate it
explicitly and call requireCanRead(actor, entity) for each entity (throwing on
unauthorized), then map each authorized entity with caseMapper.toDTO and collect
into a List to return; update the getCasesForPatient implementation to use a
simple for-loop or forEach over the fetched list (referencing
getCasesForPatient, caseRepository.findAllByPatient_Id, requireCanRead, and
caseMapper.toDTO) so authorization is performed deterministically before
mapping.
🤖 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/projektarendehantering/application/service/EmployeeService.java`:
- Around line 30-37: createEmployee currently calls employeeMapper.toEntity(dto)
without validating dto, causing a NullPointerException when dto is null; add a
null check at the start of createEmployee (after
requireCanManageEmployees(actor) or before, as preferred) using
Objects.requireNonNull(dto, "dto must not be null") or explicitly throw an
IllegalArgumentException with a clear message, so employeeMapper.toEntity(dto)
cannot return null and subsequent calls like entity.setId(...) and
entity.setCreatedAt(...) are safe; keep the rest of the logic
(employeeMapper.toEntity, entity.setId, entity.setCreatedAt,
employeeRepository.save, employeeMapper.toDTO) unchanged.

---

Nitpick comments:
In
`@src/main/java/org/example/projektarendehantering/application/service/CaseService.java`:
- Around line 110-116: The getCasesForPatient method uses Stream.peek to perform
authorization (requireCanRead) which is a misuse of peek; instead, retrieve the
List from caseRepository.findAllByPatient_Id(patientId), iterate it explicitly
and call requireCanRead(actor, entity) for each entity (throwing on
unauthorized), then map each authorized entity with caseMapper.toDTO and collect
into a List to return; update the getCasesForPatient implementation to use a
simple for-loop or forEach over the fetched list (referencing
getCasesForPatient, caseRepository.findAllByPatient_Id, requireCanRead, and
caseMapper.toDTO) so authorization is performed deterministically before
mapping.

In
`@src/main/java/org/example/projektarendehantering/application/service/EmployeeService.java`:
- Around line 45-51: The getAllEmployees method currently uses
employeeRepository.findAll(), which loads all rows into memory; change it to
accept pagination parameters (e.g., PageRequest) and use
employeeRepository.findAll(Pageable) to return a Page<EmployeeDTO> (or a
paginated DTO list) by mapping Page.getContent() via employeeMapper::toDTO, and
update method signature and callers accordingly; ensure EmployeeRepository
extends JpaRepository/PagingAndSortingRepository so findAll(Pageable) is
available and add sensible defaults (page, size, sort) and validation for those
parameters in getAllEmployees.
🪄 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: 5eca1368-2ddb-4508-8966-e967f39f35cb

📥 Commits

Reviewing files that changed from the base of the PR and between 69709df and 169cb0f.

📒 Files selected for processing (3)
  • src/main/java/org/example/projektarendehantering/application/service/CaseService.java
  • src/main/java/org/example/projektarendehantering/application/service/EmployeeService.java
  • src/main/java/org/example/projektarendehantering/presentation/rest/EmployeeController.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/org/example/projektarendehantering/presentation/rest/EmployeeController.java

Comment on lines +30 to +37
@Transactional
public EmployeeDTO createEmployee(Actor actor, EmployeeCreateDTO dto) {
requireCanManageEmployees(actor);
EmployeeEntity entity = employeeMapper.toEntity(dto);
entity.setId(UUID.randomUUID());
entity.setCreatedAt(Instant.now());
return employeeMapper.toDTO(employeeRepository.save(entity));
}
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

Add null check for dto to prevent NPE.

If dto is null, employeeMapper.toEntity(dto) returns null (per the mapper implementation), and the subsequent entity.setId() call will throw a NullPointerException. Consider validating the input early.

🛡️ Proposed fix
 `@Transactional`
 public EmployeeDTO createEmployee(Actor actor, EmployeeCreateDTO dto) {
     requireCanManageEmployees(actor);
+    if (dto == null) {
+        throw new IllegalArgumentException("EmployeeCreateDTO cannot be null");
+    }
     EmployeeEntity entity = employeeMapper.toEntity(dto);
     entity.setId(UUID.randomUUID());
     entity.setCreatedAt(Instant.now());
     return employeeMapper.toDTO(employeeRepository.save(entity));
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/org/example/projektarendehantering/application/service/EmployeeService.java`
around lines 30 - 37, createEmployee currently calls
employeeMapper.toEntity(dto) without validating dto, causing a
NullPointerException when dto is null; add a null check at the start of
createEmployee (after requireCanManageEmployees(actor) or before, as preferred)
using Objects.requireNonNull(dto, "dto must not be null") or explicitly throw an
IllegalArgumentException with a clear message, so employeeMapper.toEntity(dto)
cannot return null and subsequent calls like entity.setId(...) and
entity.setCreatedAt(...) are safe; keep the rest of the logic
(employeeMapper.toEntity, entity.setId, entity.setCreatedAt,
employeeRepository.save, employeeMapper.toDTO) unchanged.

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