Skip to content

Commit

Permalink
Merge pull request #8 from estigma88/email-notifications
Browse files Browse the repository at this point in the history
Sending emails to notify post results
  • Loading branch information
estigma88 authored May 26, 2024
2 parents d7b1a42 + ec7fdc2 commit 4315651
Show file tree
Hide file tree
Showing 18 changed files with 176 additions and 24 deletions.
7 changes: 4 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,21 @@ dependencyManagement {
dependencies {
implementation(libs.org.springframework.boot.spring.boot.starter.web)
implementation(libs.org.springframework.boot.spring.boot.starter.security)
implementation(libs.org.springframework.boot.spring.boot.starter.mail)
implementation(libs.org.springframework.boot.spring.boot.starter.oauth2.client)
implementation(libs.org.twitter4j.twitter4j.core)
implementation(libs.io.github.boostchicken.spring.data.dynamodb)
implementation(libs.com.amazonaws.serverless.aws.serverless.java.container.springboot3)
testImplementation(libs.org.springframework.boot.spring.boot.starter.test)
testImplementation(libs.org.springframework.security.spring.security.test)

itestImplementation(libs.org.springframework.cloud.spring.cloud.starter.contract.stub.runner)
itestImplementation(libs.org.springframework.boot.spring.boot.starter.test)
itestImplementation(libs.io.rest.assured.rest.assured)
itestImplementation(libs.org.mockito.mockito.core)

}

group = "com.coderstower"
version = "0.0.6-SNAPSHOT"
version = "0.0.7-SNAPSHOT"
description = "social-media-publisher"

java {
Expand Down
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ com-amazonaws-serverless-aws-serverless-java-container-springboot3 = { module =
io-github-boostchicken-spring-data-dynamodb = { module = "io.github.boostchicken:spring-data-dynamodb", version.ref = "io-github-boostchicken-spring-data-dynamodb" }
org-springframework-boot-spring-boot-starter-oauth2-client = { module = "org.springframework.boot:spring-boot-starter-oauth2-client" }
org-springframework-boot-spring-boot-starter-security = { module = "org.springframework.boot:spring-boot-starter-security"}
org-springframework-boot-spring-boot-starter-mail = { module = "org.springframework.boot:spring-boot-starter-mail"}
org-springframework-boot-spring-boot-starter-test = { module = "org.springframework.boot:spring-boot-starter-test" }
org-springframework-boot-spring-boot-starter-web = { module = "org.springframework.boot:spring-boot-starter-web" }
org-springframework-security-spring-security-test = { module = "org.springframework.security:spring-security-test" }
org-springframework-cloud-spring-cloud-starter-contract-stub-runner = { module = "org.springframework.cloud:spring-cloud-starter-contract-stub-runner" }
io-rest-assured-rest-assured = { module = "io.rest-assured:rest-assured", version.ref = "io-rest-assured-rest-assured"}
org-mockito-mockito-core = { module = "org.mockito:mockito-core"}
org-twitter4j-twitter4j-core = { module = "org.twitter4j:twitter4j-core", version.ref = "org-twitter4j-twitter4j-core" }
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.context.annotation.Import;
import org.springframework.mail.MailSender;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;

Expand All @@ -18,6 +20,9 @@
@ContextConfiguration(classes = OverriddenConfiguration.class)
@ExtendWith(ITestExtension.class)
public abstract class MockedEdgesConfig {
@MockBean
protected MailSender mailSender;

@RegisterExtension
static WireMockExtension wm1 = WireMockExtension.newInstance()
.options(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import com.coderstower.socialmediapubisher.extesion.ITestHandler;
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
import org.junit.jupiter.api.Test;
import org.springframework.mail.SimpleMailMessage;

import static org.mockito.Mockito.*;

import static io.restassured.RestAssured.given;

Expand All @@ -12,7 +15,7 @@ public class PostNextToLinkedInTest extends MockedEdgesConfig {

@Test
public void publishNextPostSuccessful(WireMockRuntimeInfo wireMockRuntimeInfo, ITestHandler iTestHandler) {
iTestHandler.loadWiremockMocks(wireMockRuntimeInfo, "testcases/post/next/linkedin/wiremock/");
iTestHandler.loadWiremockMocks(wireMockRuntimeInfo, "testcases/post/next/linkedin/success/wiremock/");

var response = given().
port(port).
Expand All @@ -23,6 +26,36 @@ public void publishNextPostSuccessful(WireMockRuntimeInfo wireMockRuntimeInfo, I
.body()
.asString();

iTestHandler.validateJSONResponse("testcases/post/next/linkedin/response.json", response);
iTestHandler.validateJSONResponse("testcases/post/next/linkedin/success/response.json", response);

SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setTo("[email protected]");
simpleMailMessage.setFrom("[email protected]");
simpleMailMessage.setSubject("SocialMediaPublisher: Success publishing group group1");
simpleMailMessage.setText("Post(id=post1, name=Post 1, description=This is a new post 1, tags=[java, code], url=http://coders.com/post1, publishedDate=2020-03-03T05:06:08.000000001, publications=[Publication(id=linkedIn123, status=SUCCESS, publisher=linkedin, credentialId=id132, publishedDate=2020-03-03T05:06:08.000000001)], group=group1)");

verify(mailSender).send(simpleMailMessage);
}

@Test
public void publishNextPostFail(WireMockRuntimeInfo wireMockRuntimeInfo, ITestHandler iTestHandler) {
iTestHandler.loadWiremockMocks(wireMockRuntimeInfo, "testcases/post/next/linkedin/failureExpiredCredentials/wiremock/");

var response = given().
port(port).
post("/posts/group1/next").
then().
statusCode(401).
extract()
.body()
.asString();

SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setTo("[email protected]");
simpleMailMessage.setFrom("[email protected]");
simpleMailMessage.setSubject("SocialMediaPublisher: Error publishing group group1");
simpleMailMessage.setText("Unauthorized for linkedin id132. Please login again here: http://localhost:8080/oauth2/linkedin/credentials");

verify(mailSender).send(simpleMailMessage);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"request": {
"method": "POST",
"url": "/",
"headers": {
"X-Amz-Target": {
"equalTo": "DynamoDB_20120810.Scan"
}
},
"bodyPatterns": [
{
"equalToJson": {
"TableName": "Oauth2Credentials"
}
}
]
},
"response": {
"status": 200,
"jsonBody": {
"Count": 1,
"Items": [
{
"id": {
"S": "id132"
},
"accessToken": {
"S": "accessToken132"
},
"expirationDate": {
"S": "2019-04-28T16:24:12"
},
"allowedGroups": {
"L": [
{
"S": "group1"
}
]
}
}
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.coderstower.socialmediapubisher.application.factory;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class MailProperties {
private final String senderEmail;
private final String receiverEmail;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.coderstower.socialmediapubisher.application.factory;

import lombok.Builder;
import lombok.Data;
import org.springframework.web.util.UriTemplate;

@Data
@Builder
public class PostProperties {
private final MailProperties mail;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ public class SocialMediaPublisherProperties {
private final Map<String, String> principalNamesAllowed;
private final CredentialsProperties credentials;
private final LinkedInProperties linkedIn;
private final PostProperties post;
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
package com.coderstower.socialmediapubisher.application.factory;

import com.coderstower.socialmediapubisher.application.socialmedia.twitter.TwitterPublisher;
import com.coderstower.socialmediapubisher.domain.post.PostPublisher;
import com.coderstower.socialmediapubisher.domain.post.repository.PostRepository;
import com.coderstower.socialmediapubisher.domain.post.socialmedia.SocialMediaPublisher;
import com.coderstower.socialmediapubisher.domain.security.OAuth2CredentialsManager;
import com.coderstower.socialmediapubisher.domain.security.repository.OAuth1CredentialsRepository;
import com.coderstower.socialmediapubisher.domain.security.repository.OAuth2CredentialsRepository;
import com.coderstower.socialmediapubisher.application.socialmedia.linkedin.LinkedInPublisher;
import com.coderstower.socialmediapubisher.application.socialmedia.twitter.TwitterPublisher;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.mail.MailSender;
import org.springframework.web.client.RestTemplate;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;
Expand All @@ -29,8 +27,8 @@ public Clock clock() {
}

@Bean
public PostPublisher postPublisher(List<SocialMediaPublisher> socialMediaPublishers, PostRepository postRepository, Clock clock) {
return new PostPublisher(socialMediaPublishers, postRepository, clock);
public PostPublisher postPublisher(List<SocialMediaPublisher> socialMediaPublishers, PostRepository postRepository, Clock clock, MailSender mailSender, SocialMediaPublisherProperties socialMediaPublisherProperties) {
return new PostPublisher(socialMediaPublishers, postRepository, clock, mailSender, socialMediaPublisherProperties.getPost().getMail().getSenderEmail(), socialMediaPublisherProperties.getPost().getMail().getReceiverEmail());
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,70 @@
import com.coderstower.socialmediapubisher.domain.post.socialmedia.Acknowledge;
import com.coderstower.socialmediapubisher.domain.post.socialmedia.Publication;
import com.coderstower.socialmediapubisher.domain.post.socialmedia.SocialMediaPublisher;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.Clock;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
public class PostPublisher {
private final List<SocialMediaPublisher> socialMediaPublishers;
private final PostRepository postRepository;
private final Clock clock;
private final MailSender mailSender;
private final String senderEmail;
private final String receiverEmail;

public PostPublisher(List<SocialMediaPublisher> socialMediaPublishers, PostRepository postRepository, Clock clock) {
public PostPublisher(List<SocialMediaPublisher> socialMediaPublishers, PostRepository postRepository, Clock clock, MailSender mailSender, String senderEmail, String receiverEmail) {
this.socialMediaPublishers = socialMediaPublishers;
this.postRepository = postRepository;
this.clock = clock;
this.mailSender = mailSender;
this.senderEmail = senderEmail;
this.receiverEmail = receiverEmail;
}

public Post publishNext(String group) {
ping(socialMediaPublishers);
try{
ping(socialMediaPublishers);

Post nextPost = postRepository.getNextToPublish(group)
.orElseThrow(() -> new IllegalStateException("There is not next post to publish"));

List<Publication> publishedPosts = publish(socialMediaPublishers, nextPost);

Post nextPost = postRepository.getNextToPublish(group)
.orElseThrow(() -> new IllegalStateException("There is not next post to publish"));
if (publishedWellOK(publishedPosts)) {
Post toUpdate = nextPost.updateLastDatePublished(LocalDateTime.now(clock));

List<Publication> publishedPosts = publish(socialMediaPublishers, nextPost);
Post postUpdated = postRepository.update(toUpdate)
.updatePublications(publishedPosts);

if (publishedWellOK(publishedPosts)) {
Post toUpdate = nextPost.updateLastDatePublished(LocalDateTime.now(clock));
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setFrom(senderEmail);
simpleMailMessage.setTo(receiverEmail);
simpleMailMessage.setSubject("SocialMediaPublisher: Success publishing group " + group);
simpleMailMessage.setText(postUpdated.toString());
mailSender.send(simpleMailMessage);

return postUpdated;
} else {
throw new IllegalStateException("Error publishing the post: " + nextPost
.updatePublications(publishedPosts));
}
} catch (Exception e) {
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setFrom(senderEmail);
simpleMailMessage.setTo(receiverEmail);
simpleMailMessage.setSubject("SocialMediaPublisher: Error publishing group " + group);
simpleMailMessage.setText(e.getMessage());
mailSender.send(simpleMailMessage);

return postRepository.update(toUpdate)
.updatePublications(publishedPosts);
} else {
throw new IllegalStateException("Error publishing the post: " + nextPost
.updatePublications(publishedPosts));
throw e;
}
}

Expand Down
15 changes: 15 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,23 @@ spring:
profiles:
group:
itest: linkedin
mail:
properties:
"[mail.smtp.auth]": true
"[mail.smtp.starttls.enable]": true
"[mail.smtp.connectiontimeout]": 5000
"[mail.smtp.timeout]": 3000
"[mail.smtp.writetimeout]": 5000
host: smtp.gmail.com
password: xxxxx
username: yyyyy
port: 587

social-media-publisher:
post:
mail:
sender-email: [email protected]
receiver-email: [email protected]
linked-in:
base-url: https://api.linkedin.com
credentials:
Expand Down

0 comments on commit 4315651

Please sign in to comment.