diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f6a92a..07ec009 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,3 +72,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Accept, Reject and request changes in project results - Notification Service - Integration in Focus and Beam +- Frontend DTO +- Email as Mime message +- EmailSenderIfError annotation +- Frontend DTO converters diff --git a/src/main/java/de/samply/annotations/EmailSenderIfError.java b/src/main/java/de/samply/annotations/EmailSenderIfError.java new file mode 100644 index 0000000..2931cc5 --- /dev/null +++ b/src/main/java/de/samply/annotations/EmailSenderIfError.java @@ -0,0 +1,17 @@ +package de.samply.annotations; + +import de.samply.email.EmailRecipientType; +import de.samply.email.EmailTemplateType; + +import java.lang.annotation.*; + +@Repeatable(EmailSendersIfError.class) +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface EmailSenderIfError { + + // Recipients of the email + EmailRecipientType[] recipients() default {}; + + EmailTemplateType templateType(); +} diff --git a/src/main/java/de/samply/annotations/EmailSendersIfError.java b/src/main/java/de/samply/annotations/EmailSendersIfError.java new file mode 100644 index 0000000..cc30d79 --- /dev/null +++ b/src/main/java/de/samply/annotations/EmailSendersIfError.java @@ -0,0 +1,12 @@ +package de.samply.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface EmailSendersIfError { + EmailSenderIfError[] value(); +} diff --git a/src/main/java/de/samply/aop/EmailSenderAspect.java b/src/main/java/de/samply/aop/EmailSenderAspect.java index da5632e..4241c5d 100644 --- a/src/main/java/de/samply/aop/EmailSenderAspect.java +++ b/src/main/java/de/samply/aop/EmailSenderAspect.java @@ -1,14 +1,14 @@ package de.samply.aop; import de.samply.annotations.EmailSender; +import de.samply.annotations.EmailSenderIfError; import de.samply.annotations.EmailSenders; +import de.samply.annotations.EmailSendersIfError; import de.samply.db.model.Project; import de.samply.db.model.ProjectBridgehead; import de.samply.db.model.ProjectBridgeheadUser; import de.samply.db.repository.*; -import de.samply.email.EmailRecipient; -import de.samply.email.EmailService; -import de.samply.email.EmailServiceException; +import de.samply.email.*; import de.samply.project.state.ProjectBridgeheadState; import de.samply.security.SessionUser; import de.samply.user.roles.OrganisationRoleToProjectRoleMapper; @@ -26,6 +26,7 @@ import java.lang.annotation.Annotation; import java.util.*; +import java.util.function.Supplier; @Component @Aspect @@ -66,33 +67,63 @@ public void emailSenderPointcut() { public void emailSendersPointcut() { } + @Pointcut("@annotation(de.samply.annotations.EmailSenderIfError)") + public void emailSenderIfErrorPointcut() { + } + + @Pointcut("@annotation(de.samply.annotations.EmailSendersIfError)") + public void emailSendersIfErrorPointcut() { + } + + @Around("emailSenderPointcut()") public Object aroundEmailSender(ProceedingJoinPoint joinPoint) throws Throwable { - return aroundEmailSender(joinPoint, true); + return aroundEmailSender(joinPoint, true, false); } @Around("emailSendersPointcut()") public Object aroundEmailSenders(ProceedingJoinPoint joinPoint) throws Throwable { - return aroundEmailSender(joinPoint, false); + return aroundEmailSender(joinPoint, false, false); } - private Object aroundEmailSender(ProceedingJoinPoint joinPoint, boolean isSingleEmailSender) throws Throwable { + @Around("emailSenderIfErrorPointcut()") + public Object aroundEmailSenderIfError(ProceedingJoinPoint joinPoint) throws Throwable { + return aroundEmailSender(joinPoint, true, true); + } + + @Around("emailSendersIfErrorPointcut()") + public Object aroundEmailSendersIfError(ProceedingJoinPoint joinPoint) throws Throwable { + return aroundEmailSender(joinPoint, false, true); + } + + private Object aroundEmailSender(ProceedingJoinPoint joinPoint, boolean isSingleEmailSender, boolean ifError) throws Throwable { try { ResponseEntity responseEntity = (ResponseEntity) joinPoint.proceed(); - if (responseEntity.getStatusCode().is2xxSuccessful()) { - sendEmail(joinPoint, isSingleEmailSender); + if (responseEntity.getStatusCode().is2xxSuccessful() ^ ifError) { + sendEmail(joinPoint, isSingleEmailSender, ifError); } return responseEntity; } catch (Exception e) { + if (ifError) { + sendEmail(joinPoint, isSingleEmailSender, ifError); + } throw new RuntimeException(e); } } - private void sendEmail(ProceedingJoinPoint joinPoint, boolean isSingleEmailSender) { + private void sendEmail(ProceedingJoinPoint joinPoint, boolean isSingleEmailSender, boolean ifError) { if (isSingleEmailSender) { - sendEmailFromEmailSender(joinPoint, fetchEmailSender(joinPoint)); + if (ifError) { + sendEmailFromEmailSenderIfError(joinPoint, fetchEmailSenderIfError(joinPoint)); + } else { + sendEmailFromEmailSender(joinPoint, fetchEmailSender(joinPoint)); + } } else { - sendEmailFromEmailSenders(joinPoint, fetchEmailSenders(joinPoint)); + if (ifError) { + sendEmailFromEmailSendersIfError(joinPoint, fetchEmailSendersIfError(joinPoint)); + } else { + sendEmailFromEmailSenders(joinPoint, fetchEmailSenders(joinPoint)); + } } } @@ -102,13 +133,23 @@ private void sendEmailFromEmailSenders(ProceedingJoinPoint joinPoint, Optional emailSenderOptional) { - emailSenderOptional.ifPresent(emailSender -> fetchEmailRecipients(emailSender, joinPoint) - .forEach(emailRecipient -> sendEmail(emailRecipient, emailSender))); + emailSenderOptional.ifPresent(emailSender -> fetchEmailRecipients(() -> emailSender.recipients(), joinPoint) + .forEach(emailRecipient -> sendEmail(emailRecipient, () -> emailSender.templateType()))); + } + + private void sendEmailFromEmailSendersIfError(ProceedingJoinPoint joinPoint, Optional emailSendersIfErrorOptional) { + emailSendersIfErrorOptional.ifPresent(emailSendersIfError -> Arrays.stream(emailSendersIfError.value()).forEach(emailSenderIfError -> + sendEmailFromEmailSenderIfError(joinPoint, Optional.of(emailSenderIfError)))); } - private void sendEmail(EmailRecipient emailRecipient, EmailSender emailSender) { + private void sendEmailFromEmailSenderIfError(ProceedingJoinPoint joinPoint, Optional emailSenderIfErrorOptional) { + emailSenderIfErrorOptional.ifPresent(emailSenderIfError -> fetchEmailRecipients(() -> emailSenderIfError.recipients(), joinPoint) + .forEach(emailRecipient -> sendEmail(emailRecipient, () -> emailSenderIfError.templateType()))); + } + + private void sendEmail(EmailRecipient emailRecipient, Supplier emailTemplateTypeSupplier) { try { - emailService.sendEmail(emailRecipient.email(), emailRecipient.bridgehead(), emailRecipient.role(), emailSender.templateType()); + emailService.sendEmail(emailRecipient.email(), emailRecipient.bridgehead(), emailRecipient.role(), emailTemplateTypeSupplier.get()); } catch (EmailServiceException e) { throw new RuntimeException(e); } @@ -122,12 +163,20 @@ private Optional fetchEmailSenders(JoinPoint joinPoint) { return AspectUtils.fetchT(joinPoint, EmailSenders.class); } - private Set fetchEmailRecipients(EmailSender emailSender, ProceedingJoinPoint joinPoint) { + private Optional fetchEmailSenderIfError(JoinPoint joinPoint) { + return AspectUtils.fetchT(joinPoint, EmailSenderIfError.class); + } + + private Optional fetchEmailSendersIfError(JoinPoint joinPoint) { + return AspectUtils.fetchT(joinPoint, EmailSendersIfError.class); + } + + private Set fetchEmailRecipients(Supplier emailRecipientTypesSupplier, ProceedingJoinPoint joinPoint) { Set result = new HashSet<>(); Optional projectCode = AspectUtils.fetchProjectCode(joinPoint); Optional bridgehead = AspectUtils.fetchBridghead(joinPoint); Optional email = AspectUtils.fetchEmail(joinPoint); - Arrays.stream(emailSender.recipients()).forEach(emailRecipientType -> + Arrays.stream(emailRecipientTypesSupplier.get()).forEach(emailRecipientType -> result.addAll(switch (emailRecipientType) { case SESSION_USER -> fetchEmailRecipientsForSessionUser(projectCode, bridgehead); case EMAIL_ANNOTATION -> fetchEmailRecipientsForEmailAnnotation(projectCode, bridgehead, email); @@ -247,9 +296,8 @@ private Set fetchProjectBridgeheads(Optional projectC private Set fetchEmailRecipientsForProjectManagerAdmin() { Set result = new HashSet<>(); - projectManagerAdminUserRepository.findAll().forEach(projectManagerAdminUser -> { - result.add(new EmailRecipient(projectManagerAdminUser.getEmail(), Optional.empty(), ProjectRole.PROJECT_MANAGER_ADMIN)); - }); + projectManagerAdminUserRepository.findAll().forEach(projectManagerAdminUser -> + result.add(new EmailRecipient(projectManagerAdminUser.getEmail(), Optional.empty(), ProjectRole.PROJECT_MANAGER_ADMIN))); return result; } diff --git a/src/main/java/de/samply/db/model/ProjectBridgehead.java b/src/main/java/de/samply/db/model/ProjectBridgehead.java index 6c36368..7f2f3ac 100644 --- a/src/main/java/de/samply/db/model/ProjectBridgehead.java +++ b/src/main/java/de/samply/db/model/ProjectBridgehead.java @@ -33,6 +33,6 @@ public class ProjectBridgehead { private ProjectBridgeheadState state = ProjectBridgeheadState.CREATED; @Column(name = "modified_at", nullable = false) - private Instant modifiedAt; + private Instant modifiedAt = Instant.now(); } diff --git a/src/main/java/de/samply/document/DocumentService.java b/src/main/java/de/samply/document/DocumentService.java index e19c2f0..d9ef97a 100644 --- a/src/main/java/de/samply/document/DocumentService.java +++ b/src/main/java/de/samply/document/DocumentService.java @@ -5,6 +5,7 @@ import de.samply.db.model.ProjectDocument; import de.samply.db.repository.ProjectDocumentRepository; import de.samply.db.repository.ProjectRepository; +import de.samply.frontend.dto.DtoFactory; import de.samply.security.SessionUser; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -192,12 +193,17 @@ public Optional fetchApplicationForm() { return fetchPublicDocument(applicationFormFile); } - public List fetchPublications(String projectCode) { - return fetchDocuments(projectCode, Optional.empty(), DocumentType.PUBLICATION); + public List fetchPublications(String projectCode) { + return convertToDto(fetchDocuments(projectCode, Optional.empty(), DocumentType.PUBLICATION)); + + } + + private List convertToDto(List projectDocumentList){ + return projectDocumentList.stream().map(DtoFactory::convert).toList(); } - public List fetchOtherDocuments(String projectCode, Optional bridgehead) { - return fetchDocuments(projectCode, bridgehead, DocumentType.OTHERS); + public List fetchOtherDocuments(String projectCode, Optional bridgehead) { + return convertToDto(fetchDocuments(projectCode, bridgehead, DocumentType.OTHERS)); } diff --git a/src/main/java/de/samply/email/EmailService.java b/src/main/java/de/samply/email/EmailService.java index ac79be1..f0da63b 100644 --- a/src/main/java/de/samply/email/EmailService.java +++ b/src/main/java/de/samply/email/EmailService.java @@ -2,11 +2,13 @@ import de.samply.app.ProjectManagerConst; import de.samply.user.roles.ProjectRole; +import jakarta.mail.MessagingException; +import jakarta.mail.internet.MimeMessage; import jakarta.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; -import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; import org.thymeleaf.TemplateEngine; import org.thymeleaf.context.Context; @@ -43,22 +45,34 @@ public void sendEmail(@NotNull String email, Optional bridgehead, @NotNu } public void sendEmail(@NotNull String email, Optional bridgehead, @NotNull ProjectRole role, @NotNull EmailTemplateType type, Map keyValues) throws EmailServiceException { - SimpleMailMessage message = new SimpleMailMessage(); Map context = new HashMap<>(); bridgehead.ifPresent(b -> context.put(ProjectManagerConst.EMAIL_CONTEXT_BRIDGEHEAD, b)); context.putAll(keyValues); context.putAll(emailContext.getKeyValues()); Optional messageSubject = createEmailMessageAndSubject(role, type, context); if (messageSubject.isPresent()) { - message.setTo(email); - message.setFrom(emailFrom); - message.setSubject(messageSubject.get().subject()); - message.setText(messageSubject.get().message()); - mailSender.send(message); + mailSender.send(createMimeMessage(email, emailFrom, messageSubject.get())); } else { throw new EmailServiceException("Template not found for " + type.name() + " of role " + role.name()); } + } + + private MimeMessage createMimeMessage(String emailTo, String emailFrom, MessageSubject messageSubject) throws EmailServiceException { + try { + return createMimeMessageWithoutHandlingException(emailTo, emailFrom, messageSubject); + } catch (MessagingException e) { + throw new EmailServiceException(e); + } + } + private MimeMessage createMimeMessageWithoutHandlingException(String emailTo, String emailFrom, MessageSubject messageSubject) throws MessagingException { + MimeMessage message = mailSender.createMimeMessage(); + MimeMessageHelper messageHelper = new MimeMessageHelper(message, true); + messageHelper.setTo(emailTo); + message.setFrom(emailFrom); + message.setSubject(messageSubject.subject()); + message.setText(messageSubject.message()); + return message; } private Optional createEmailMessageAndSubject(ProjectRole role, EmailTemplateType type, Map keyValues) { diff --git a/src/main/java/de/samply/email/EmailServiceException.java b/src/main/java/de/samply/email/EmailServiceException.java index 08d7fc9..973a7ea 100644 --- a/src/main/java/de/samply/email/EmailServiceException.java +++ b/src/main/java/de/samply/email/EmailServiceException.java @@ -6,4 +6,8 @@ public EmailServiceException(String message) { super(message); } + public EmailServiceException(Throwable cause) { + super(cause); + } + } diff --git a/src/main/java/de/samply/frontend/dto/DtoFactory.java b/src/main/java/de/samply/frontend/dto/DtoFactory.java new file mode 100644 index 0000000..44b7aba --- /dev/null +++ b/src/main/java/de/samply/frontend/dto/DtoFactory.java @@ -0,0 +1,66 @@ +package de.samply.frontend.dto; + +import de.samply.project.state.ProjectBridgeheadState; +import jakarta.validation.constraints.NotNull; + +import java.time.Instant; + +public class DtoFactory { + + public static Project convert(@NotNull de.samply.db.model.Project project) { + return new Project( + project.getCode(), + project.getCreatorEmail(), + project.getCreatedAt(), + project.getExpiresAt(), + project.getArchivedAt(), + project.getModifiedAt(), + project.getState(), + project.getType(), + project.getQuery().getQuery(), + project.getQuery().getHumanReadable(), + project.getQuery().getQueryFormat(), + project.getQuery().getOutputFormat(), + project.getQuery().getTemplateId(), + project.getQuery().getLabel(), + project.getQuery().getDescription(), + project.getQuery().getExplorerUrl(), + project.getQuery().getContext() + ); + } + + public static Notification convert(@NotNull de.samply.db.model.Notification notification) { + return new Notification( + notification.getEmail(), + notification.getTimestamp(), + notification.getProject().getCode(), + notification.getBridgehead(), + notification.getOperationType(), + notification.getDetails(), + notification.getError() + ); + } + + public static ProjectDocument convert(@NotNull de.samply.db.model.ProjectDocument projectDocument) { + return new ProjectDocument( + projectDocument.getProject().getCode(), + projectDocument.getOriginalFilename(), + projectDocument.getUrl(), + projectDocument.getCreatedAt(), + projectDocument.getBridgehead(), + projectDocument.getCreatorEmail(), + projectDocument.getLabel(), + projectDocument.getDocumentType() + ); + } + + public static ProjectBridgehead convert(@NotNull de.samply.db.model.ProjectBridgehead projectBridgehead) { + return new ProjectBridgehead( + projectBridgehead.getProject().getCode(), + projectBridgehead.getBridgehead(), + projectBridgehead.getState(), + projectBridgehead.getModifiedAt() + ); + } + +} diff --git a/src/main/java/de/samply/frontend/dto/Notification.java b/src/main/java/de/samply/frontend/dto/Notification.java new file mode 100644 index 0000000..d56ed4b --- /dev/null +++ b/src/main/java/de/samply/frontend/dto/Notification.java @@ -0,0 +1,16 @@ +package de.samply.frontend.dto; + +import de.samply.notification.OperationType; + +import java.time.Instant; + +public record Notification( + String email, + Instant timestamp, + String projectCode, + String bridgehead, + OperationType operationType, + String details, + String error +) { +} diff --git a/src/main/java/de/samply/frontend/dto/Project.java b/src/main/java/de/samply/frontend/dto/Project.java new file mode 100644 index 0000000..c962172 --- /dev/null +++ b/src/main/java/de/samply/frontend/dto/Project.java @@ -0,0 +1,30 @@ +package de.samply.frontend.dto; + +import de.samply.project.ProjectType; +import de.samply.project.state.ProjectState; +import de.samply.query.OutputFormat; +import de.samply.query.QueryFormat; + +import java.time.Instant; +import java.time.LocalDate; + +public record Project( + String code, + String creatorEmail, + Instant createdAt, + LocalDate expiresAt, + Instant archivedAt, + Instant modifiedAt, + ProjectState state, + ProjectType type, + String query, + String humanReadable, + QueryFormat queryFormat, + OutputFormat outputFormat, + String templateId, + String label, + String description, + String explorerUrl, + String queryContext +) { +} diff --git a/src/main/java/de/samply/frontend/dto/ProjectBridgehead.java b/src/main/java/de/samply/frontend/dto/ProjectBridgehead.java new file mode 100644 index 0000000..4c29a88 --- /dev/null +++ b/src/main/java/de/samply/frontend/dto/ProjectBridgehead.java @@ -0,0 +1,13 @@ +package de.samply.frontend.dto; + +import de.samply.project.state.ProjectBridgeheadState; + +import java.time.Instant; + +public record ProjectBridgehead( + String projectCode, + String bridgehead, + ProjectBridgeheadState state, + Instant modifiedAt +) { +} diff --git a/src/main/java/de/samply/frontend/dto/ProjectDocument.java b/src/main/java/de/samply/frontend/dto/ProjectDocument.java new file mode 100644 index 0000000..173d8b9 --- /dev/null +++ b/src/main/java/de/samply/frontend/dto/ProjectDocument.java @@ -0,0 +1,18 @@ +package de.samply.frontend.dto; + +import de.samply.document.DocumentType; + +import java.time.Instant; + +public record ProjectDocument( + String projectCode, + String originalFilename, + String url, + Instant createdAt, + String bridgehead, + String creatorEmail, + String label, + DocumentType type +) { + +} diff --git a/src/main/java/de/samply/notification/NotificationService.java b/src/main/java/de/samply/notification/NotificationService.java index fb6d222..791a702 100644 --- a/src/main/java/de/samply/notification/NotificationService.java +++ b/src/main/java/de/samply/notification/NotificationService.java @@ -4,6 +4,7 @@ import de.samply.db.model.Project; import de.samply.db.repository.NotificationRepository; import de.samply.db.repository.ProjectRepository; +import de.samply.frontend.dto.DtoFactory; import jakarta.validation.constraints.NotNull; import org.springframework.stereotype.Service; @@ -22,7 +23,8 @@ public NotificationService(NotificationRepository notificationRepository, this.projectRepository = projectRepository; } - public void createNotification(@NotNull String projectCode, String bridgehead, @NotNull String email, @NotNull OperationType operationType, + public void createNotification(@NotNull String projectCode, String bridgehead, @NotNull String email, + @NotNull OperationType operationType, @NotNull String details, String error ) throws NotificationServiceException { Project project = fetchProject(projectCode); @@ -44,11 +46,12 @@ private Project fetchProject(String projectCode) throws NotificationServiceExcep return project.get(); } - public List fetchNotifications(String projectCode, Optional bridghead) throws NotificationServiceException { + public List fetchNotifications(String projectCode, Optional bridghead) throws NotificationServiceException { Project project = fetchProject(projectCode); - return (bridghead.isEmpty()) ? + return ((bridghead.isEmpty()) ? notificationRepository.findAllByProjectOrderByTimestampDesc(project) : - notificationRepository.findAllByProjectAndBridgeheadOrBridgeheadIsNullOrderByTimestampDesc(project, bridghead.get()); + notificationRepository.findAllByProjectAndBridgeheadOrBridgeheadIsNullOrderByTimestampDesc(project, bridghead.get())) + .stream().map(DtoFactory::convert).toList(); } diff --git a/src/main/java/de/samply/notification/NotificationServiceException.java b/src/main/java/de/samply/notification/NotificationServiceException.java index f9b68ee..9ba8431 100644 --- a/src/main/java/de/samply/notification/NotificationServiceException.java +++ b/src/main/java/de/samply/notification/NotificationServiceException.java @@ -1,6 +1,6 @@ package de.samply.notification; -public class NotificationServiceException extends Exception { +public class NotificationServiceException extends RuntimeException { public NotificationServiceException(String message) { super(message); } diff --git a/src/main/java/de/samply/notification/OperationType.java b/src/main/java/de/samply/notification/OperationType.java index 57963bf..55ac213 100644 --- a/src/main/java/de/samply/notification/OperationType.java +++ b/src/main/java/de/samply/notification/OperationType.java @@ -1,4 +1,5 @@ package de.samply.notification; public enum OperationType { + GENERATE_TOKEN } diff --git a/src/main/java/de/samply/project/ProjectBridgeheadService.java b/src/main/java/de/samply/project/ProjectBridgeheadService.java index 087ba5d..3db6220 100644 --- a/src/main/java/de/samply/project/ProjectBridgeheadService.java +++ b/src/main/java/de/samply/project/ProjectBridgeheadService.java @@ -5,6 +5,7 @@ import de.samply.db.repository.ProjectBridgeheadRepository; import de.samply.db.repository.ProjectBridgeheadUserRepository; import de.samply.db.repository.ProjectRepository; +import de.samply.frontend.dto.DtoFactory; import de.samply.project.state.ProjectBridgeheadState; import de.samply.security.SessionUser; import de.samply.user.roles.OrganisationRole; @@ -52,14 +53,14 @@ private void changeProjectBridgeheadState(@NotNull String projectCode, @NotNull projectBridgeheadRepository.save(projectBridgehead.get()); } - public List fetchUserVisibleProjectBridgeheads(@NotNull String projectCode) throws ProjectBridgeheadServiceException { + public List fetchUserVisibleProjectBridgeheads(@NotNull String projectCode) throws ProjectBridgeheadServiceException { Optional project = projectRepository.findByCode(projectCode); if (project.isEmpty()) { throw new ProjectBridgeheadServiceException("Project " + projectCode + " not found"); } Set projectBridgeheads = projectBridgeheadRepository.findByProject(project.get()); if (isProjectManagerAdmin()) { - return new ArrayList<>(projectBridgeheads); + return new ArrayList<>(projectBridgeheads).stream().map(DtoFactory::convert).toList(); } Set tempProjectBridgeheads = new HashSet<>(); projectBridgeheads.forEach(projectBridgehead -> { @@ -67,7 +68,7 @@ public List fetchUserVisibleProjectBridgeheads(@NotNull Strin tempProjectBridgeheads.add(projectBridgehead); } }); - return new ArrayList<>(tempProjectBridgeheads); + return new ArrayList<>(tempProjectBridgeheads).stream().map(DtoFactory::convert).toList(); } private boolean isProjectManagerAdmin() { diff --git a/src/main/java/de/samply/project/ProjectService.java b/src/main/java/de/samply/project/ProjectService.java index 4061a2d..0629d1a 100644 --- a/src/main/java/de/samply/project/ProjectService.java +++ b/src/main/java/de/samply/project/ProjectService.java @@ -4,6 +4,7 @@ import de.samply.db.model.ProjectBridgehead; import de.samply.db.repository.ProjectBridgeheadRepository; import de.samply.db.repository.ProjectRepository; +import de.samply.frontend.dto.DtoFactory; import de.samply.project.state.ProjectBridgeheadState; import de.samply.project.state.ProjectState; import de.samply.security.SessionUser; @@ -73,18 +74,18 @@ private void createProjectBridgehead(Project project, String bridgehead) { projectBridgeheadRepository.save(projectBridgehead); } - public Page fetchUserVisibleProjects( + public Page fetchUserVisibleProjects( Optional projectState, Optional archived, int page, int pageSize, boolean modifiedDescendant) { PageRequest pageRequest = PageRequest.of(page, pageSize); if (isProjectManagerAdmin()) { - return fetchProjectManagerAdminProjects(projectState, archived, pageRequest, modifiedDescendant); + return fetchProjectManagerAdminProjects(projectState, archived, pageRequest, modifiedDescendant).map(DtoFactory::convert); } Set bridgeheads = sessionUser.getBridgeheads(); // We make an assumption: A bridgehead admin is bridgehead admin in all of their bridgeheads. if (isBridgeheadAdmin()) { - return fetchBridgeheadAdminProjects(bridgeheads, projectState, archived, pageRequest, modifiedDescendant); + return fetchBridgeheadAdminProjects(bridgeheads, projectState, archived, pageRequest, modifiedDescendant).map(DtoFactory::convert); } - return fetchResearcherProjects(sessionUser.getEmail(), bridgeheads, projectState, archived, pageRequest, modifiedDescendant); + return fetchResearcherProjects(sessionUser.getEmail(), bridgeheads, projectState, archived, pageRequest, modifiedDescendant).map(DtoFactory::convert); } private boolean isProjectManagerAdmin() {