-
Notifications
You must be signed in to change notification settings - Fork 0
Employee entity etc #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package org.example.projektarendehantering.application.service; | ||
|
|
||
| import org.example.projektarendehantering.infrastructure.persistence.EmployeeEntity; | ||
| import org.example.projektarendehantering.presentation.dto.EmployeeCreateDTO; | ||
| import org.example.projektarendehantering.presentation.dto.EmployeeDTO; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| @Component | ||
| public class EmployeeMapper { | ||
|
|
||
| public EmployeeDTO toDTO(EmployeeEntity entity) { | ||
| if (entity == null) return null; | ||
| return new EmployeeDTO( | ||
| entity.getId(), | ||
| entity.getDisplayName(), | ||
| entity.getRole(), | ||
| entity.getCreatedAt() | ||
| ); | ||
| } | ||
|
|
||
| public EmployeeEntity toEntity(EmployeeCreateDTO dto) { | ||
| if (dto == null) return null; | ||
| EmployeeEntity entity = new EmployeeEntity(); | ||
| entity.setDisplayName(dto.getDisplayName()); | ||
| entity.setRole(dto.getRole()); | ||
| return entity; | ||
| } | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,63 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package org.example.projektarendehantering.application.service; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.example.projektarendehantering.common.Actor; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.example.projektarendehantering.common.NotAuthorizedException; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.example.projektarendehantering.common.Role; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.example.projektarendehantering.infrastructure.persistence.EmployeeEntity; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.example.projektarendehantering.infrastructure.persistence.EmployeeRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.example.projektarendehantering.presentation.dto.EmployeeCreateDTO; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.example.projektarendehantering.presentation.dto.EmployeeDTO; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.stereotype.Service; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import org.springframework.transaction.annotation.Transactional; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.time.Instant; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.Optional; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.UUID; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.stream.Collectors; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Service | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public class EmployeeService { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final EmployeeRepository employeeRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final EmployeeMapper employeeMapper; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public EmployeeService(EmployeeRepository employeeRepository, EmployeeMapper employeeMapper) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.employeeRepository = employeeRepository; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.employeeMapper = employeeMapper; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @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)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Transactional(readOnly = true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public Optional<EmployeeDTO> getEmployee(Actor actor, UUID id) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| requireCanManageEmployees(actor); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return employeeRepository.findById(id).map(employeeMapper::toDTO); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Transactional(readOnly = true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public List<EmployeeDTO> getAllEmployees(Actor actor) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| requireCanManageEmployees(actor); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return employeeRepository.findAll().stream() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map(employeeMapper::toDTO) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .collect(Collectors.toList()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+30
to
+50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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 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");
+ }
+ }
}
📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private void requireCanManageEmployees(Actor actor) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (actor == null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new NotAuthorizedException("Missing actor"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (actor.role() == Role.MANAGER || actor.role() == Role.ADMIN) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new NotAuthorizedException("Not allowed to access employees"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| package org.example.projektarendehantering.infrastructure.persistence; | ||
|
|
||
| import jakarta.persistence.Entity; | ||
| import jakarta.persistence.EnumType; | ||
| import jakarta.persistence.Enumerated; | ||
| import jakarta.persistence.Id; | ||
| import jakarta.persistence.Table; | ||
| import org.example.projektarendehantering.common.Role; | ||
|
|
||
| import java.time.Instant; | ||
| import java.util.UUID; | ||
|
|
||
| @Entity | ||
| @Table(name = "employees") | ||
| public class EmployeeEntity { | ||
|
|
||
| @Id | ||
| private UUID id; | ||
|
|
||
| private String displayName; | ||
|
|
||
| @Enumerated(EnumType.STRING) | ||
| private Role role; | ||
|
|
||
| private Instant createdAt; | ||
|
|
||
| public EmployeeEntity() {} | ||
|
|
||
| public EmployeeEntity(UUID id, String displayName, Role role, Instant createdAt) { | ||
| this.id = id; | ||
| this.displayName = displayName; | ||
| this.role = role; | ||
| this.createdAt = createdAt; | ||
| } | ||
|
|
||
| public UUID getId() { return id; } | ||
| public void setId(UUID id) { this.id = id; } | ||
|
|
||
| public String getDisplayName() { return displayName; } | ||
| public void setDisplayName(String displayName) { this.displayName = displayName; } | ||
|
|
||
| public Role getRole() { return role; } | ||
| public void setRole(Role role) { this.role = role; } | ||
|
|
||
| public Instant getCreatedAt() { return createdAt; } | ||
| public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add null check for dto to prevent NPE.
If
dtois null,employeeMapper.toEntity(dto)returns null (per the mapper implementation), and the subsequententity.setId()call will throw aNullPointerException. 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