diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cf4dfd..5d19d6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,3 +74,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Integration in Focus and Beam - Frontend DTO - Email as Mime message +- EmailSenderIfError annotation 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; }