diff --git a/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/PostController.java b/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/PostController.java index 6760001f..b9a2b181 100644 --- a/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/PostController.java +++ b/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/PostController.java @@ -1,29 +1,48 @@ package de.mrsebastian.todoappdemo.backend.graphql; -import de.mrsebastian.todoappdemo.backend.person.rest.PersonDTO; +import de.mrsebastian.todoappdemo.backend.graphql.types.Person; +import de.mrsebastian.todoappdemo.backend.graphql.types.Task; +import de.mrsebastian.todoappdemo.backend.graphql.types.TaskOfPerson; +import de.mrsebastian.todoappdemo.backend.graphql.types.TypeMapper; import de.mrsebastian.todoappdemo.backend.person.service.PersonService; -import de.mrsebastian.todoappdemo.backend.task.rest.TaskDTO; import de.mrsebastian.todoappdemo.backend.task.service.TaskService; +import java.util.Collections; import java.util.List; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.graphql.data.method.annotation.QueryMapping; +import org.springframework.graphql.data.method.annotation.SchemaMapping; import org.springframework.stereotype.Controller; @Controller @RequiredArgsConstructor +@Slf4j public class PostController { private final TaskService taskService; private final PersonService personService; + private final TypeMapper typeMapper; + @QueryMapping - public List getTasks() { - return taskService.getTasks(); + public List getTasks() { + return taskService.getTasks().stream().map(taskDTO -> typeMapper.taskDtoToTaskType(taskDTO, null)).toList(); } @QueryMapping - public List getPersons() { - return personService.getPersonen(); + public List getPersons() { + return personService.getPersonen().stream().map(typeMapper::personDtoToPersonType).toList(); + } + + @SchemaMapping + public List tasks(Person person) { + log.atDebug().log("collection tasks of person with id > {}", person.id()); + + if (person.id() == null) { + return Collections.emptyList(); + } + + return taskService.getTaskWithAssignee(person.id()).stream().map(typeMapper::taskDtoToTaskOfPersonType).toList(); } } diff --git a/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/types/Person.java b/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/types/Person.java new file mode 100644 index 00000000..fa2a2d17 --- /dev/null +++ b/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/types/Person.java @@ -0,0 +1,7 @@ +package de.mrsebastian.todoappdemo.backend.graphql.types; + +import jakarta.validation.constraints.NotNull; +import java.util.UUID; + +public record Person(@NotNull UUID id, String firstname, String lastname, @NotNull String email) { +} diff --git a/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/types/Task.java b/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/types/Task.java new file mode 100644 index 00000000..90e982fe --- /dev/null +++ b/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/types/Task.java @@ -0,0 +1,9 @@ +package de.mrsebastian.todoappdemo.backend.graphql.types; + +import de.mrsebastian.todoappdemo.backend.person.dataaccess.entity.Person; +import jakarta.validation.constraints.NotNull; +import java.util.UUID; + +public record Task(@NotNull UUID id, @NotNull String title, @NotNull String description, String dueDate, + Person creator, UUID assigneeId, Person assignee) { +} diff --git a/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/types/TaskOfPerson.java b/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/types/TaskOfPerson.java new file mode 100644 index 00000000..073a0ad7 --- /dev/null +++ b/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/types/TaskOfPerson.java @@ -0,0 +1,8 @@ +package de.mrsebastian.todoappdemo.backend.graphql.types; + +import jakarta.validation.constraints.NotNull; +import java.util.UUID; + +public record TaskOfPerson(@NotNull UUID id, @NotNull String title, @NotNull String description, String dueDate, + UUID creatorId, UUID assigneeId) { +} diff --git a/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/types/TypeMapper.java b/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/types/TypeMapper.java new file mode 100644 index 00000000..279f1981 --- /dev/null +++ b/backend/src/main/java/de/mrsebastian/todoappdemo/backend/graphql/types/TypeMapper.java @@ -0,0 +1,18 @@ +package de.mrsebastian.todoappdemo.backend.graphql.types; + +import de.mrsebastian.todoappdemo.backend.person.rest.PersonDTO; +import de.mrsebastian.todoappdemo.backend.task.rest.TaskDTO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +@Mapper +public interface TypeMapper { + + Person personDtoToPersonType(PersonDTO personDTO); + + @Mapping(target = "id", source = "taskDTO.id") + Task taskDtoToTaskType(TaskDTO taskDTO, PersonDTO assignee); + + @Mapping(target = "creatorId", source = "creator.id") + TaskOfPerson taskDtoToTaskOfPersonType(TaskDTO taskDTO); +} diff --git a/backend/src/main/java/de/mrsebastian/todoappdemo/backend/task/service/TaskService.java b/backend/src/main/java/de/mrsebastian/todoappdemo/backend/task/service/TaskService.java index 682c6feb..446f8a15 100644 --- a/backend/src/main/java/de/mrsebastian/todoappdemo/backend/task/service/TaskService.java +++ b/backend/src/main/java/de/mrsebastian/todoappdemo/backend/task/service/TaskService.java @@ -43,6 +43,13 @@ public List getTasks() { return taskDAService.getTasks().stream().map(taskMapper::toDTO).toList(); } + @PreAuthorize( + "hasAnyRole(T(de.mrsebastian.todoappdemo.backend.security.AuthoritiesEnum).TASK_ADMIN.name(), T(de.mrsebastian.todoappdemo.backend.security.AuthoritiesEnum).TASK_READER.name())" + ) + public List getTaskWithAssignee(final UUID assigneeId) { + return getTasks().stream().filter(task -> assigneeId.equals(task.assigneeId())).toList(); + } + @PreAuthorize("hasAnyRole(T(de.mrsebastian.todoappdemo.backend.security.AuthoritiesEnum).TASK_ADMIN.name())") public void deleteTask(final UUID taskId) { checkIfExistsOrThrow(taskId); diff --git a/backend/src/main/resources/graphql/tasks.graphqls b/backend/src/main/resources/graphql/tasks.graphqls index 752d2b7d..28a7aa60 100644 --- a/backend/src/main/resources/graphql/tasks.graphqls +++ b/backend/src/main/resources/graphql/tasks.graphqls @@ -4,6 +4,8 @@ type Task { description: String!, dueDate: String creator: Person + assigneeId: ID + assignee: Person } type Person { @@ -11,6 +13,16 @@ type Person { firstname: String lastname: String, email: String! + tasks: [TaskOfPerson] +} + +type TaskOfPerson { + id: ID! + title: String!, + description: String!, + dueDate: String + creatorId: ID + assigneeId: ID } type Query { diff --git a/backend/src/main/resources/logback-spring.xml b/backend/src/main/resources/logback-spring.xml index d1f9b41d..4305880e 100644 --- a/backend/src/main/resources/logback-spring.xml +++ b/backend/src/main/resources/logback-spring.xml @@ -44,6 +44,12 @@ + + + + diff --git a/backend/src/test/resources/persons.graphql.http b/backend/src/test/resources/persons.graphql.http index 450901dc..ff1bbc6a 100644 --- a/backend/src/test/resources/persons.graphql.http +++ b/backend/src/test/resources/persons.graphql.http @@ -5,9 +5,26 @@ GRAPHQL http://localhost:39146/graphql query { getPersons { - id - firstname - lastname - email + id + firstname + lastname + email + } +} + +### GraphQL Persons with Tasks +GRAPHQL http://localhost:39146/graphql + +query { + getPersons { + id + firstname + lastname + email + tasks { + id + title + description + } } } \ No newline at end of file