Skip to content

Commit f58f619

Browse files
committed
Send out additional emails
Fixes #253
1 parent d9f737d commit f58f619

File tree

16 files changed

+312
-33
lines changed

16 files changed

+312
-33
lines changed

src/inttest/java/com/faforever/api/data/BanInfoTest.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package com.faforever.api.data;
22

33
import com.faforever.api.AbstractIntegrationTest;
4+
import com.faforever.api.email.EmailSender;
45
import com.faforever.api.player.PlayerRepository;
56
import org.junit.Test;
7+
import org.mockito.ArgumentMatchers;
8+
import org.mockito.Mockito;
69
import org.springframework.beans.factory.annotation.Autowired;
10+
import org.springframework.boot.test.mock.mockito.MockBean;
711
import org.springframework.security.test.context.support.WithUserDetails;
812
import org.springframework.test.context.jdbc.Sql;
913
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;
@@ -46,9 +50,11 @@ public class BanInfoTest extends AbstractIntegrationTest {
4650
}
4751
}
4852
*/
49-
private static final String testPost = "{\"data\":{\"type\":\"banInfo\",\"attributes\":{\"level\":\"CHAT\",\"reason\":\"This test ban should be revoked\"},\"relationships\":{\"author\":{\"data\":{\"type\":\"player\",\"id\":\"1\"}},\"player\":{\"data\":{\"type\":\"player\",\"id\":\"3\"}}}}}";
53+
private static final String testPost = "{\"data\":{\"type\":\"banInfo\",\"attributes\":{\"level\":\"CHAT\",\"reason\":\"This test ban should be revoked\"},\"relationships\":{\"author\":{\"data\":{\"type\":\"player\",\"id\":\"2\"}},\"player\":{\"data\":{\"type\":\"player\",\"id\":\"3\"}}}}}";
5054
@Autowired
5155
PlayerRepository playerRepository;
56+
@MockBean
57+
private EmailSender emailSender;
5258

5359
@Test
5460
@WithUserDetails(AUTH_USER)
@@ -98,5 +104,11 @@ public void canCreateBanInfoAsModerator() throws Exception {
98104
.andExpect(status().isCreated());
99105

100106
assertThat(playerRepository.getOne(3).getBans().size(), is(1));
107+
Mockito.verify(emailSender).sendMail(ArgumentMatchers.eq("[email protected]"),
108+
ArgumentMatchers.eq("[email protected]"),
109+
ArgumentMatchers.eq("[email protected]"),
110+
ArgumentMatchers.eq("ban subject"),
111+
ArgumentMatchers.matches("Hello ADMIN,\\|Your account was banned\\|Reason - This test ban should be revoked\\|Banner - MODERATOR\\|Time - (.)*\\|Type - CHAT\\|Expires - never\\|Thank you for your fairness and acceptance[.]")
112+
);
101113
}
102114
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.faforever.api.data;
2+
3+
import com.faforever.api.AbstractIntegrationTest;
4+
import com.faforever.api.data.domain.BanStatus;
5+
import com.faforever.api.email.EmailSender;
6+
import com.faforever.api.player.PlayerRepository;
7+
import org.junit.Ignore;
8+
import org.junit.Test;
9+
import org.mockito.Mockito;
10+
import org.springframework.beans.factory.annotation.Autowired;
11+
import org.springframework.boot.test.mock.mockito.MockBean;
12+
import org.springframework.security.test.context.support.WithUserDetails;
13+
import org.springframework.test.context.jdbc.Sql;
14+
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;
15+
16+
import static org.hamcrest.core.Is.is;
17+
import static org.junit.Assert.assertThat;
18+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
19+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
20+
21+
@Sql(executionPhase = ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:sql/prepDefaultUser.sql")
22+
@Sql(executionPhase = ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:sql/prepBanRevokeData.sql")
23+
@Sql(executionPhase = ExecutionPhase.AFTER_TEST_METHOD, scripts = "classpath:sql/cleanBanRevokeData.sql")
24+
public class BanRevokeElideTest extends AbstractIntegrationTest {
25+
@MockBean
26+
private EmailSender emailSender;
27+
@Autowired
28+
private PlayerRepository playerRepository;
29+
/*
30+
{"data":{"type":"banRevokeData","attributes":{"reason":"unban"},"relationships":{"ban":{"data":{"type":"banInfo","id":"1"}},"author":{"data":{"type":"player","id":"2"}}}}} */
31+
private static final String TEST_REVOKE="{\"data\":{\"type\":\"banRevokeData\",\"attributes\":{\"reason\":\"unban\"},\"relationships\":{\"ban\":{\"data\":{\"type\":\"banInfo\",\"id\":\"1\"}},\"author\":{\"data\":{\"type\":\"player\",\"id\":\"2\"}}}}}";
32+
33+
@Ignore(value = "Posting of ban revokes never worked, moderator use to change expire date instead see issue #259")
34+
@WithUserDetails(AUTH_MODERATOR)
35+
@Test
36+
public void testRevokeBanWithId1() throws Exception {
37+
assertThat(playerRepository.getOne(4).getBans().size(), is(1));
38+
assertThat(playerRepository.getOne(4).getBans().iterator().next().getBanStatus(), is(BanStatus.BANNED));
39+
40+
mockMvc.perform(post("/data/banRevokeData")
41+
.content(TEST_REVOKE))
42+
.andExpect(status().isCreated());
43+
44+
assertThat(playerRepository.getOne(4).getBans().iterator().next().getBanStatus(), is(BanStatus.DISABLED));
45+
Mockito.verify(emailSender).sendMail("","","","","");
46+
}
47+
}

src/inttest/resources/config/application.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ faf-api:
6666
mautic:
6767
client-id: banana
6868
client-secret: banana
69+
username-change:
70+
mail-body: ${USERNAME_CHANGE_EMAIL_BODY:Hello {0},| your username changed to {1}}
71+
mail-subject: ${USERNAME_CHANGE_EMAIL_SUBJECT:Username changed}
72+
ban:
73+
ban-mail-body: ${BAN_EMAIL_BODY:Hello {0},|Your account was banned|Reason - {1}|Banner - {2}|Time - {3}|Type - {4}|Expires - {5}|Thank you for your fairness and acceptance.}
74+
ban-mail-subject: ${BAN_EMAIL_SUBJECT:ban subject}
75+
ban-revoke-mail-body: ${BAN_REVOKE_EMAIL_BODY:Hello {0},|Your account was been unbanned.|Moderator that unbanned you - {1}|Reason - {2}|Original reason of the ban - {3}|original banner - {4}|Time of original ban - {5}.|Thank you for your fairness and acceptance.}
76+
ban-revoke-mail-subject: ${BAN_REVOKE_EMAIL_SUBJECT:email ban revoke subject}
6977

7078

7179
logging:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
DELETE FROM ban_revoke;
2+
DELETE FROM ban;

src/inttest/resources/sql/prepBanData.sql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ INSERT INTO login (id, login, email, password) VALUES
55
(4, 'BANNED', '[email protected]', 'not relevant');
66

77
INSERT INTO ban (id, player_id, author_id, reason, expires_at, level) VALUES
8-
(1, 4, 1, 'Test permaban', DATE_ADD(NOW(), INTERVAL 1 DAY), 'GLOBAL'),
9-
(2, 2, 1, 'To be revoked ban', DATE_ADD(NOW(), INTERVAL 1 DAY), 'GLOBAL');
8+
(1, 4, 2, 'Test permaban', DATE_ADD(NOW(), INTERVAL 1 DAY), 'GLOBAL'),
9+
(2, 2, 2, 'To be revoked ban', DATE_ADD(NOW(), INTERVAL 1 DAY), 'GLOBAL');
1010

1111
INSERT INTO ban_revoke (ban_id, reason, author_id) VALUES
12-
(2, 'Test revoke', 1);
12+
(2, 'Test revoke', 2);
1313

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
DELETE FROM ban_revoke;
2+
DELETE FROM ban;
3+
4+
INSERT INTO login (id, login, email, password) VALUES
5+
(4, 'BANNED', '[email protected]', 'not relevant');
6+
7+
INSERT INTO ban (id, player_id, author_id, reason, expires_at, level) VALUES
8+
(1, 4, 2, 'Test permaban', DATE_ADD(NOW(), INTERVAL 1 DAY), 'GLOBAL');

src/main/java/com/faforever/api/config/FafApiProperties.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ public class FafApiProperties {
3939
private Anope anope = new Anope();
4040
private Rating rating = new Rating();
4141
private Tutorial tutorial = new Tutorial();
42+
private UsernameChange usernameChange = new UsernameChange();
43+
private Ban ban = new Ban();
4244

4345
@Data
4446
public static class OAuth2 {
@@ -250,4 +252,18 @@ public class Rating {
250252
public static class Tutorial {
251253
private String thumbnailUrlFormat;
252254
}
255+
256+
@Data
257+
public class UsernameChange {
258+
private String mailBody;
259+
private String mailSubject;
260+
}
261+
262+
@Data
263+
public class Ban {
264+
private String banMailBody;
265+
private String banMailSubject;
266+
private String banRevokeMailBody;
267+
private String banRevokeMailSubject;
268+
}
253269
}

src/main/java/com/faforever/api/config/elide/ElideConfig.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,15 @@
88
import com.faforever.api.data.checks.permission.HasBanUpdate;
99
import com.faforever.api.data.checks.permission.HasLadder1v1Update;
1010
import com.faforever.api.data.checks.permission.IsModerator;
11+
import com.faforever.api.data.domain.BanInfo;
12+
import com.faforever.api.data.domain.BanRevokeData;
13+
import com.faforever.api.data.listeners.BanInfoPostCreateListener;
14+
import com.faforever.api.data.listeners.BanRevokePostCreateListener;
1115
import com.faforever.api.security.ExtendedAuditLogger;
1216
import com.fasterxml.jackson.databind.ObjectMapper;
1317
import com.yahoo.elide.Elide;
1418
import com.yahoo.elide.ElideSettingsBuilder;
19+
import com.yahoo.elide.annotation.OnCreatePostCommit;
1520
import com.yahoo.elide.core.EntityDictionary;
1621
import com.yahoo.elide.core.filter.dialect.RSQLFilterDialect;
1722
import com.yahoo.elide.jsonapi.JsonApiMapper;
@@ -37,18 +42,22 @@ public class ElideConfig {
3742
public static final String DEFAULT_CACHE_NAME = "Elide.defaultCache";
3843

3944
@Bean
40-
public Elide elide(SpringHibernateDataStore springHibernateDataStore, ObjectMapper objectMapper, EntityDictionary entityDictionary, ExtendedAuditLogger extendedAuditLogger) {
45+
public Elide elide(SpringHibernateDataStore springHibernateDataStore, ObjectMapper objectMapper, EntityDictionary entityDictionary,
46+
ExtendedAuditLogger extendedAuditLogger, BanInfoPostCreateListener banInfoPostCreateListener, BanRevokePostCreateListener banRevokePostCreateListener) {
4147
RSQLFilterDialect rsqlFilterDialect = new RSQLFilterDialect(entityDictionary);
4248

4349
registerAdditionalConverters();
4450

45-
return new Elide(new ElideSettingsBuilder(springHibernateDataStore)
51+
Elide elide = new Elide(new ElideSettingsBuilder(springHibernateDataStore)
4652
.withJsonApiMapper(new JsonApiMapper(entityDictionary, objectMapper))
4753
.withAuditLogger(extendedAuditLogger)
4854
.withEntityDictionary(entityDictionary)
4955
.withJoinFilterDialect(rsqlFilterDialect)
5056
.withSubqueryFilterDialect(rsqlFilterDialect)
5157
.build());
58+
entityDictionary.bindTrigger(BanInfo.class, OnCreatePostCommit.class, banInfoPostCreateListener);
59+
entityDictionary.bindTrigger(BanRevokeData.class, OnCreatePostCommit.class, banRevokePostCreateListener);
60+
return elide;
5261
}
5362

5463
@Bean
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.faforever.api.data.listeners;
2+
3+
import com.faforever.api.data.domain.BanDurationType;
4+
import com.faforever.api.data.domain.BanInfo;
5+
import com.faforever.api.data.domain.Player;
6+
import com.faforever.api.email.EmailService;
7+
import com.yahoo.elide.functions.LifeCycleHook;
8+
import com.yahoo.elide.security.RequestScope;
9+
import lombok.extern.slf4j.Slf4j;
10+
import org.springframework.stereotype.Component;
11+
12+
import javax.inject.Inject;
13+
import javax.validation.constraints.NotNull;
14+
import java.time.OffsetDateTime;
15+
import java.time.format.DateTimeFormatter;
16+
import java.util.Optional;
17+
18+
@Component
19+
@Slf4j
20+
public class BanInfoPostCreateListener implements LifeCycleHook<BanInfo> {
21+
22+
private final EmailService emailService;
23+
24+
@Inject
25+
public BanInfoPostCreateListener(EmailService emailService) {
26+
this.emailService = emailService;
27+
}
28+
29+
@Override
30+
public void execute(BanInfo elideEntity, RequestScope requestScope, Optional changes) {
31+
try {
32+
@NotNull Player player = elideEntity.getPlayer();
33+
emailService.sendBanMail(player.getEmail(),
34+
player.getLogin(),
35+
elideEntity.getReason(),
36+
elideEntity.getAuthor().getLogin(),
37+
OffsetDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME),
38+
elideEntity.getLevel().name(),
39+
elideEntity.getDuration() == BanDurationType.PERMANENT ? "never" : elideEntity.getExpiresAt().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
40+
} catch (Exception e) {
41+
log.error("Sending ban email failed", e);
42+
}
43+
}
44+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.faforever.api.data.listeners;
2+
3+
import com.faforever.api.data.domain.BanInfo;
4+
import com.faforever.api.data.domain.BanRevokeData;
5+
import com.faforever.api.data.domain.Player;
6+
import com.faforever.api.email.EmailService;
7+
import com.yahoo.elide.functions.LifeCycleHook;
8+
import com.yahoo.elide.security.ChangeSpec;
9+
import com.yahoo.elide.security.RequestScope;
10+
import lombok.extern.slf4j.Slf4j;
11+
import org.springframework.stereotype.Component;
12+
13+
import javax.validation.constraints.NotNull;
14+
import java.time.format.DateTimeFormatter;
15+
import java.util.Optional;
16+
17+
@Slf4j
18+
@Component
19+
public class BanRevokePostCreateListener implements LifeCycleHook<BanRevokeData> {
20+
private final EmailService emailService;
21+
22+
public BanRevokePostCreateListener(EmailService emailService) {
23+
this.emailService = emailService;
24+
}
25+
26+
@Override
27+
public void execute(BanRevokeData banRevoke, RequestScope requestScope, Optional<ChangeSpec> changes) {
28+
try {
29+
@NotNull BanInfo ban = banRevoke.getBan();
30+
@NotNull Player player = ban.getPlayer();
31+
emailService.sendBanRevokeMail(player.getEmail(),
32+
player.getLogin(),
33+
banRevoke.getAuthor().getLogin(),
34+
banRevoke.getReason(),
35+
ban.getReason(),
36+
ban.getAuthor().getLogin(),
37+
ban.getCreateTime().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
38+
} catch (Exception e) {
39+
log.error("Failed to send ban revoke email", e);
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)