diff --git a/Readme.md b/Readme.md index 12b8cef..384d19a 100644 --- a/Readme.md +++ b/Readme.md @@ -12,7 +12,7 @@ Spin up container with: ``` docker network create track-debts-net docker run -d -v ./data:/var/lib/postgresql/data -e POSTGRES_DB=track-debts --network track-debts-net --name track-debts-pg postgres -docker run -d --network track-debts-net -e "LIQPAY_PUBLIC_KEY=" -e "LIQPAY_PRIVATE_KEY=" -e "APP_SECRET=" -e DB_HOST=track-debts-pg -e DB_PORT=5432 --name track-debts freefly19/track-debts +docker run -d --network track-debts-net -e "LIQPAY_PUBLIC_KEY=" -e "LIQPAY_PRIVATE_KEY=" -e "APP_SECRET=" -e DB_HOST=track-debts-pg -e DB_PORT=5432 -e SMTP_HOST=smtp.google.com -e SMTP_PORT=587 -e SMTP_USERNAME= -e SMTP_PASSWORD= -e SMTP_START_TLS=true --name track-debts freefly19/track-debts ``` _**secret** should be longer than 86 chars_ diff --git a/build.gradle b/build.gradle index 84b4b11..13ad949 100644 --- a/build.gradle +++ b/build.gradle @@ -33,9 +33,14 @@ dependencies { compile('com.spencerwi:Either.java:2.0.0') + compile 'org.springframework.boot:spring-boot-starter-mail:2.1.3.RELEASE' + compile('io.springfox:springfox-swagger2:2.9.2') compile('io.springfox:springfox-swagger-ui:2.9.2') + compile group: 'org.thymeleaf', name: 'thymeleaf', version: '3.0.11.RELEASE' + compile group: 'org.thymeleaf', name: 'thymeleaf-spring5', version: '3.0.11.RELEASE' + compile('io.jsonwebtoken:jjwt-api:0.10.5') runtime('io.jsonwebtoken:jjwt-impl:0.10.5') runtime('io.jsonwebtoken:jjwt-jackson:0.10.5') diff --git a/dev/docker-compose.yaml b/dev/docker-compose.yaml index a7c9bf4..8e99c1b 100644 --- a/dev/docker-compose.yaml +++ b/dev/docker-compose.yaml @@ -13,4 +13,9 @@ services: environment: POSTGRES_DB: track-debts-test ports: - - 5434:5432 \ No newline at end of file + - 5434:5432 + track-debts-mailhog: + image: mailhog/mailhog + ports: + - "1021:1025" + - "8021:8025" \ No newline at end of file diff --git a/src/main/java/com/freefly19/trackdebts/TrackDebtsApplication.java b/src/main/java/com/freefly19/trackdebts/TrackDebtsApplication.java index 6d3bebb..fea9278 100644 --- a/src/main/java/com/freefly19/trackdebts/TrackDebtsApplication.java +++ b/src/main/java/com/freefly19/trackdebts/TrackDebtsApplication.java @@ -5,10 +5,12 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableAsync; import java.util.Date; @SpringBootApplication(exclude = SecurityAutoConfiguration.class) +@EnableAsync public class TrackDebtsApplication { @Bean diff --git a/src/main/java/com/freefly19/trackdebts/bill/user/BillUserCreatedEvent.java b/src/main/java/com/freefly19/trackdebts/bill/user/BillUserCreatedEvent.java new file mode 100644 index 0000000..d8af3b9 --- /dev/null +++ b/src/main/java/com/freefly19/trackdebts/bill/user/BillUserCreatedEvent.java @@ -0,0 +1,11 @@ +package com.freefly19.trackdebts.bill.user; + +import com.freefly19.trackdebts.AppEvent; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public class BillUserCreatedEvent implements AppEvent { + private final long billUserId; +} diff --git a/src/main/java/com/freefly19/trackdebts/bill/user/BillUserService.java b/src/main/java/com/freefly19/trackdebts/bill/user/BillUserService.java index 3db25be..8c5e049 100644 --- a/src/main/java/com/freefly19/trackdebts/bill/user/BillUserService.java +++ b/src/main/java/com/freefly19/trackdebts/bill/user/BillUserService.java @@ -2,11 +2,13 @@ import com.freefly19.trackdebts.bill.Bill; import com.freefly19.trackdebts.bill.BillRepository; +import com.freefly19.trackdebts.notification.EmailService; import com.freefly19.trackdebts.security.UserRequestContext; import com.freefly19.trackdebts.user.UserDto; import com.freefly19.trackdebts.user.UserRepository; import com.spencerwi.either.Either; import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -24,6 +26,7 @@ public class BillUserService { private final BillUserRepository billUserRepository; private final UserRepository userRepository; private final BillRepository billRepository; + private final ApplicationEventPublisher eventPublisher; @Transactional public Either> save(UserRequestContext context, CreateBillUserCommand command, Long billId) { @@ -57,6 +60,8 @@ public Either> save(UserRequestContext context, Cr return billUserRepository.save(bu); }); + eventPublisher.publishEvent(new BillUserCreatedEvent(billUser.getId())); + return Either.right(Optional.of(new BillUserDto(billUser))); } diff --git a/src/main/java/com/freefly19/trackdebts/BillLockToMoneyTransactionHandler.java b/src/main/java/com/freefly19/trackdebts/eventhandlers/BillLockToMoneyTransactionHandler.java similarity index 98% rename from src/main/java/com/freefly19/trackdebts/BillLockToMoneyTransactionHandler.java rename to src/main/java/com/freefly19/trackdebts/eventhandlers/BillLockToMoneyTransactionHandler.java index 797fc7d..8b16b4d 100644 --- a/src/main/java/com/freefly19/trackdebts/BillLockToMoneyTransactionHandler.java +++ b/src/main/java/com/freefly19/trackdebts/eventhandlers/BillLockToMoneyTransactionHandler.java @@ -1,4 +1,4 @@ -package com.freefly19.trackdebts; +package com.freefly19.trackdebts.eventhandlers; import com.freefly19.trackdebts.bill.Bill; import com.freefly19.trackdebts.bill.BillRepository; diff --git a/src/main/java/com/freefly19/trackdebts/eventhandlers/BillUserCreatedEmailGeneratorHandler.java b/src/main/java/com/freefly19/trackdebts/eventhandlers/BillUserCreatedEmailGeneratorHandler.java new file mode 100644 index 0000000..70b1ad8 --- /dev/null +++ b/src/main/java/com/freefly19/trackdebts/eventhandlers/BillUserCreatedEmailGeneratorHandler.java @@ -0,0 +1,40 @@ +package com.freefly19.trackdebts.eventhandlers; + +import com.freefly19.trackdebts.bill.user.BillUser; +import com.freefly19.trackdebts.bill.user.BillUserCreatedEvent; +import com.freefly19.trackdebts.bill.user.BillUserRepository; +import com.freefly19.trackdebts.notification.Email; +import com.freefly19.trackdebts.notification.EmailService; +import lombok.RequiredArgsConstructor; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; +import org.thymeleaf.TemplateEngine; +import org.thymeleaf.context.Context; + +@RequiredArgsConstructor +@Component +public class BillUserCreatedEmailGeneratorHandler { + private final EmailService emailService; + private final TemplateEngine templateEngine; + private final BillUserRepository repository; + + @EventListener + public void onBillUserCreatedEvent(BillUserCreatedEvent event) { + BillUser billUser = repository.getOne(event.getBillUserId()); + Email email = Email.builder() + .sender("no-reply@track-debts.com") + .receiver(billUser.getUser().getEmail()) + .subject("You've been added to " + billUser.getBill().getTitle() + " bill") + .body(templateForBillUserEmail(billUser)) + .build(); + emailService.sendNotification(email); + } + + private String templateForBillUserEmail(BillUser billUser) { + Context context = new Context(); + context.setVariable("USER", billUser.getUser().getDisplayName()); + context.setVariable("BILL", billUser.getBill().getTitle()); + + return templateEngine.process("email", context); + } +} diff --git a/src/main/java/com/freefly19/trackdebts/notification/Email.java b/src/main/java/com/freefly19/trackdebts/notification/Email.java new file mode 100644 index 0000000..110c5fa --- /dev/null +++ b/src/main/java/com/freefly19/trackdebts/notification/Email.java @@ -0,0 +1,15 @@ +package com.freefly19.trackdebts.notification; + +import lombok.Builder; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Builder +@RequiredArgsConstructor +@Getter +public class Email { + private final String sender; + private final String receiver; + private final String subject; + private final String body; +} diff --git a/src/main/java/com/freefly19/trackdebts/notification/EmailService.java b/src/main/java/com/freefly19/trackdebts/notification/EmailService.java new file mode 100644 index 0000000..13c7e59 --- /dev/null +++ b/src/main/java/com/freefly19/trackdebts/notification/EmailService.java @@ -0,0 +1,34 @@ +package com.freefly19.trackdebts.notification; + +import lombok.RequiredArgsConstructor; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; + +@RequiredArgsConstructor +@Service +public class EmailService { + private final JavaMailSender javaEmailSender; + + @Async + public void sendNotification(Email mail) { + MimeMessage email = javaEmailSender.createMimeMessage(); + + try { + MimeMessageHelper helper = new MimeMessageHelper(email, true); + + helper.setFrom(mail.getSender()); + helper.setTo(mail.getReceiver()); + helper.setSubject(mail.getSubject()); + helper.setText(mail.getBody(), true); + + javaEmailSender.send(email); + } catch (MessagingException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/freefly19/trackdebts/user/User.java b/src/main/java/com/freefly19/trackdebts/user/User.java index fc1f0c7..ac919be 100644 --- a/src/main/java/com/freefly19/trackdebts/user/User.java +++ b/src/main/java/com/freefly19/trackdebts/user/User.java @@ -9,6 +9,7 @@ import javax.persistence.*; import java.util.ArrayList; import java.util.List; +import java.util.Optional; @NoArgsConstructor @AllArgsConstructor @@ -29,4 +30,14 @@ public class User { @OneToMany(mappedBy = "user") private List billUsers = new ArrayList<>(); + public String getFullName() { + if (firstName == null) { + return Optional.ofNullable(lastName).orElse(null); + } + return firstName + (lastName == null ? "" : (" " + lastName)); + } + + public String getDisplayName() { + return Optional.ofNullable(getFullName()).orElse(email); + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1a3b1f0..ebbadda 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -9,3 +9,10 @@ spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL95Dialect spring.datasource.url=jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5433}/track-debts spring.datasource.username=${DB_USERNAME:postgres} spring.datasource.password=${DB_PASSWORD:} + +spring.mail.host=${SMTP_HOST:localhost} +spring.mail.port=${SMTP_PORT:1021} +spring.mail.username=${SMTP_USERNAME:user@test.com} +spring.mail.password=${SMTP_PASSWORD:somepass} +spring.mail.properties.mail.smtp.auth=true +spring.mail.properties.mail.smtp.starttls.enable=${SMTP_START_TLS:false} \ No newline at end of file diff --git a/src/main/resources/templates/BillUserCreatedEmailNotification.html b/src/main/resources/templates/BillUserCreatedEmailNotification.html new file mode 100644 index 0000000..ef170dc --- /dev/null +++ b/src/main/resources/templates/BillUserCreatedEmailNotification.html @@ -0,0 +1,72 @@ + + + + + Check + + + + + + +
+ + + + + + + +
+ +

Track debts

+
+ + + + + + + + +
+ +
+
+
+ +