Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package org.example.projektarendehantering.application.service;

import org.example.projektarendehantering.common.Actor;
import org.example.projektarendehantering.infrastructure.persistence.CaseNoteEntity;
import org.example.projektarendehantering.presentation.dto.CaseNoteDTO;
import org.springframework.stereotype.Component;

import java.time.Instant;

@Component
public class CaseNoteMapper {

Expand All @@ -12,7 +15,9 @@ public CaseNoteDTO toDTO(CaseNoteEntity entity) {
return new CaseNoteDTO(
entity.getId(),
entity.getContent(),
entity.getAuthor(),
entity.getAuthorDisplayName(),
entity.getAuthorGithubUsername(),
entity.getAuthorRole(),
entity.getCreatedAt()
);
}
Expand All @@ -22,8 +27,21 @@ public CaseNoteEntity toEntity(CaseNoteDTO dto) {
CaseNoteEntity entity = new CaseNoteEntity();
entity.setId(dto.getId());
entity.setContent(dto.getContent());
entity.setAuthor(dto.getAuthor());
entity.setAuthorDisplayName(dto.getAuthorDisplayName());
entity.setAuthorGithubUsername(dto.getAuthorGithubUsername());
entity.setAuthorRole(dto.getAuthorRole());
entity.setCreatedAt(dto.getCreatedAt());
return entity;
}

public CaseNoteEntity toEntity(Actor actor, String content) {
if (actor == null) return null;
CaseNoteEntity entity = new CaseNoteEntity();
entity.setContent(content);
entity.setAuthorDisplayName(actor.displayName());
entity.setAuthorGithubUsername(actor.githubUsername());
entity.setAuthorRole(actor.role() != null ? actor.role().name() : null);
entity.setCreatedAt(Instant.now());
return entity;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,31 @@ public class CaseService {

private final CaseRepository caseRepository;
private final CaseMapper caseMapper;
private final CaseNoteMapper caseNoteMapper;
private final PatientRepository patientRepository;
private final CaseNoteRepository caseNoteRepository;
private final EmployeeRepository employeeRepository;

public CaseService(CaseRepository caseRepository, CaseMapper caseMapper, PatientRepository patientRepository, CaseNoteRepository caseNoteRepository, EmployeeRepository employeeRepository) {
public CaseService(CaseRepository caseRepository, CaseMapper caseMapper, CaseNoteMapper caseNoteMapper, PatientRepository patientRepository, CaseNoteRepository caseNoteRepository, EmployeeRepository employeeRepository) {
this.caseRepository = caseRepository;
this.caseMapper = caseMapper;
this.caseNoteMapper = caseNoteMapper;
this.patientRepository = patientRepository;
this.caseNoteRepository = caseNoteRepository;
this.employeeRepository = employeeRepository;
}

@Transactional
public void addNote(UUID caseId, String content, String author) {
public void addNote(UUID caseId, String content, Actor actor) {
if (actor == null) {
throw new NotAuthorizedException("Not allowed to add notes");
}
CaseEntity caseEntity = caseRepository.findById(caseId)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Case not found"));
requireCanRead(actor, caseEntity);

CaseNoteEntity note = new CaseNoteEntity();
CaseNoteEntity note = caseNoteMapper.toEntity(actor, content);
note.setCaseEntity(caseEntity);
note.setContent(content);
note.setAuthor(author);
note.setCreatedAt(Instant.now());

caseNoteRepository.save(note);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import org.example.projektarendehantering.presentation.dto.EmployeeDTO;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.UUID;

@Component
public class EmployeeMapper {

Expand All @@ -13,6 +16,7 @@ public EmployeeDTO toDTO(EmployeeEntity entity) {
return new EmployeeDTO(
entity.getId(),
entity.getDisplayName(),
entity.getGithubUsername(),
entity.getRole(),
entity.getCreatedAt()
);
Expand All @@ -22,7 +26,13 @@ public EmployeeEntity toEntity(EmployeeCreateDTO dto) {
if (dto == null) return null;
EmployeeEntity entity = new EmployeeEntity();
entity.setDisplayName(dto.getDisplayName());
entity.setGithubUsername(dto.getGithubUsername());
entity.setRole(dto.getRole());

if (dto.getGithubUsername() != null && !dto.getGithubUsername().isBlank()) {
UUID id = UUID.nameUUIDFromBytes(dto.getGithubUsername().getBytes(StandardCharsets.UTF_8));
entity.setId(id);
}
return entity;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.example.projektarendehantering.application.service;

import org.example.projektarendehantering.common.Actor;
import org.example.projektarendehantering.common.BadRequestException;
import org.example.projektarendehantering.common.NotAuthorizedException;
import org.example.projektarendehantering.common.Role;
import org.example.projektarendehantering.infrastructure.persistence.EmployeeEntity;
Expand Down Expand Up @@ -30,8 +31,15 @@ public EmployeeService(EmployeeRepository employeeRepository, EmployeeMapper emp
@Transactional
public EmployeeDTO createEmployee(Actor actor, EmployeeCreateDTO dto) {
requireCanManageEmployees(actor);

if (employeeRepository.findByGithubUsername(dto.getGithubUsername()).isPresent()) {
throw new BadRequestException("EMPLOYEE_EXISTS", "Employee with username " + dto.getGithubUsername() + " already exists");
}

EmployeeEntity entity = employeeMapper.toEntity(dto);
entity.setId(UUID.randomUUID());
if (entity.getId() == null) {
entity.setId(UUID.randomUUID());
}
entity.setCreatedAt(Instant.now());
return employeeMapper.toDTO(employeeRepository.save(entity));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.util.UUID;

public record Actor(UUID userId, Role role) {
public record Actor(UUID userId, Role role, String displayName, String githubUsername) {


}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
Expand All @@ -12,6 +13,7 @@

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ public class CaseNoteEntity {

private String content;

private String author;
private String authorDisplayName;
private String authorGithubUsername;
private String authorRole;

private Instant createdAt;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.example.projektarendehantering.infrastructure.persistence;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
Expand All @@ -19,16 +20,20 @@ public class EmployeeEntity {

private String displayName;

@Column(unique = true)
private String githubUsername;

@Enumerated(EnumType.STRING)
private Role role;

private Instant createdAt;

public EmployeeEntity() {}

public EmployeeEntity(UUID id, String displayName, Role role, Instant createdAt) {
public EmployeeEntity(UUID id, String displayName, String githubUsername, Role role, Instant createdAt) {
this.id = id;
this.displayName = displayName;
this.githubUsername = githubUsername;
this.role = role;
this.createdAt = createdAt;
}
Expand All @@ -39,6 +44,9 @@ public EmployeeEntity(UUID id, String displayName, Role role, Instant createdAt)
public String getDisplayName() { return displayName; }
public void setDisplayName(String displayName) { this.displayName = displayName; }

public String getGithubUsername() { return githubUsername; }
public void setGithubUsername(String githubUsername) { this.githubUsername = githubUsername; }

public Role getRole() { return role; }
public void setRole(Role role) { this.role = role; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;
import java.util.UUID;

public interface EmployeeRepository extends JpaRepository<EmployeeEntity, UUID> {
Optional<EmployeeEntity> findByGithubUsername(String githubUsername);
}

Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import org.example.projektarendehantering.common.Actor;
import org.example.projektarendehantering.common.NotAuthorizedException;
import org.example.projektarendehantering.common.Role;
import org.example.projektarendehantering.infrastructure.persistence.EmployeeRepository;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
Expand All @@ -16,16 +18,39 @@
@Component
public class SecurityActorAdapter {

private final EmployeeRepository employeeRepository;

public SecurityActorAdapter(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}

public Actor currentUser() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

if (authentication == null || !authentication.isAuthenticated() || "anonymousUser".equals(authentication.getName())) {
throw new NotAuthorizedException("User not authenticated");
}

// Try to find the username (GitHub 'login' attribute) or fallback to name
String name = authentication.getName();
if (authentication instanceof OAuth2AuthenticationToken oauth2Token) {
String login = oauth2Token.getPrincipal().getAttribute("login");
if (login != null) {
name = login;
}
}

// Create a deterministic UUID based on the username/name
UUID userId = UUID.nameUUIDFromBytes(authentication.getName().getBytes(StandardCharsets.UTF_8));
UUID userId = UUID.nameUUIDFromBytes(name.getBytes(StandardCharsets.UTF_8));

// 1. Try finding an employee with this UUID
var employee = employeeRepository.findById(userId);
if (employee.isPresent()) {
var e = employee.get();
return new Actor(userId, e.getRole(), e.getDisplayName(), e.getGithubUsername());
}

// 2. Fallback to existing logic (checking Spring authorities)
Role role = Role.PATIENT;
if (authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_MANAGER"))) {
role = Role.MANAGER;
Expand All @@ -37,6 +62,6 @@ public Actor currentUser() {
role = Role.PATIENT;
}

return new Actor(userId, role);
return new Actor(userId, role, null, name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@ public class CaseNoteDTO {

private UUID id;
private String content;
private String author;
private String authorDisplayName;
private String authorGithubUsername;
private String authorRole;
private Instant createdAt;

public CaseNoteDTO() {}

public CaseNoteDTO(UUID id, String content, String author, Instant createdAt) {
public CaseNoteDTO(UUID id, String content, String authorDisplayName, String authorGithubUsername, String authorRole, Instant createdAt) {
this.id = id;
this.content = content;
this.author = author;
this.authorDisplayName = authorDisplayName;
this.authorGithubUsername = authorGithubUsername;
this.authorRole = authorRole;
this.createdAt = createdAt;
}

Expand All @@ -25,8 +29,14 @@ public CaseNoteDTO(UUID id, String content, String author, Instant createdAt) {
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }

public String getAuthor() { return author; }
public void setAuthor(String author) { this.author = author; }
public String getAuthorDisplayName() { return authorDisplayName; }
public void setAuthorDisplayName(String authorDisplayName) { this.authorDisplayName = authorDisplayName; }

public String getAuthorGithubUsername() { return authorGithubUsername; }
public void setAuthorGithubUsername(String authorGithubUsername) { this.authorGithubUsername = authorGithubUsername; }

public String getAuthorRole() { return authorRole; }
public void setAuthorRole(String authorRole) { this.authorRole = authorRole; }

public Instant getCreatedAt() { return createdAt; }
public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,26 @@ public class EmployeeCreateDTO {
@NotBlank
private String displayName;

@NotBlank
private String githubUsername;

@NotNull
private Role role;

public EmployeeCreateDTO() {}

public EmployeeCreateDTO(String displayName, Role role) {
public EmployeeCreateDTO(String displayName, String githubUsername, Role role) {
this.displayName = displayName;
this.githubUsername = githubUsername;
this.role = role;
}

public String getDisplayName() { return displayName; }
public void setDisplayName(String displayName) { this.displayName = displayName; }

public String getGithubUsername() { return githubUsername; }
public void setGithubUsername(String githubUsername) { this.githubUsername = githubUsername; }

public Role getRole() { return role; }
public void setRole(Role role) { this.role = role; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ public class EmployeeDTO {

private UUID id;
private String displayName;
private String githubUsername;
private Role role;
private Instant createdAt;

public EmployeeDTO() {}

public EmployeeDTO(UUID id, String displayName, Role role, Instant createdAt) {
public EmployeeDTO(UUID id, String displayName, String githubUsername, Role role, Instant createdAt) {
this.id = id;
this.displayName = displayName;
this.githubUsername = githubUsername;
this.role = role;
this.createdAt = createdAt;
}
Expand All @@ -27,6 +29,9 @@ public EmployeeDTO(UUID id, String displayName, Role role, Instant createdAt) {
public String getDisplayName() { return displayName; }
public void setDisplayName(String displayName) { this.displayName = displayName; }

public String getGithubUsername() { return githubUsername; }
public void setGithubUsername(String githubUsername) { this.githubUsername = githubUsername; }

public Role getRole() { return role; }
public void setRole(Role role) { this.role = role; }

Expand Down
Loading