Skip to content

Commit def12e4

Browse files
authored
Merge pull request #4071 from kofzera/send_notifications_bulk
feat(core): resend notifications method
2 parents f08df95 + 352d9e2 commit def12e4

File tree

5 files changed

+137
-8
lines changed

5 files changed

+137
-8
lines changed

perun-openapi/openapi.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16466,6 +16466,39 @@ paths:
1646616466
appId: { type: integer, description: "application id" }
1646716467
reason: { type: string, description: "you can specify reason for case: mailType == APP_REJECTED_USER" }
1646816468

16469+
/json/registrarManager/sendMessages:
16470+
post:
16471+
tags:
16472+
- RegistrarManager
16473+
operationId: sendMessages
16474+
summary: Manually re-sends mail notifications for existing applications.
16475+
description: |
16476+
Expected to be called as a result of direct VO administrator action in the web UI.
16477+
responses:
16478+
'200':
16479+
$ref: '#/components/responses/VoidResponse'
16480+
default:
16481+
$ref: '#/components/responses/ExceptionResponse'
16482+
requestBody:
16483+
required: true
16484+
content:
16485+
application/json:
16486+
schema:
16487+
title: InputSendMessages
16488+
description: "input to sendMessages"
16489+
type: object
16490+
required:
16491+
- mailType
16492+
- ids
16493+
properties:
16494+
mailType: { $ref: '#/components/schemas/MailType' }
16495+
reason: { type: string, description: "you can specify reason for case: mailType == APP_REJECTED_USER" }
16496+
ids:
16497+
type: array
16498+
items:
16499+
type: integer
16500+
description: "An array of integers representing the IDs of applications"
16501+
1646916502
/json/registrarManager/getApplicationForm/vo:
1647016503
get:
1647116504
tags:

perun-registrar-lib/src/main/java/cz/metacentrum/perun/registrar/MailManager.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,16 @@ public interface MailManager {
155155
*/
156156
void sendMessage(PerunSession sess, Application app, MailType mailType, String reason) throws PerunException;
157157

158+
/**
159+
* Manually re-send multiple notifications at once. Expected to be called as a result of direct VO administrator action in the web UI.
160+
*
161+
* @param sess PerunSession for authz
162+
* @param applications application to send notification for
163+
* @param mailType MailType action which caused sending
164+
* @param reason custom text passed to mail by admin (e.g. reason of application reject)
165+
*/
166+
void sendMessages(PerunSession sess, List<Application> applications, MailType mailType, String reason) throws PerunException;
167+
158168
/**
159169
* Send invitations with link to VO / Group application form from provided csv data
160170
*

perun-registrar-lib/src/main/java/cz/metacentrum/perun/registrar/impl/MailManagerImpl.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -576,12 +576,12 @@ public void sendMessage(PerunSession sess, Application app, MailType mailType, S
576576
ApplicationForm form = getForm(app);
577577

578578
ApplicationMail mail = getMailByParams(form.getId(), app.getType(), mailType);
579-
if (mail == null) throw new RegistrarException("Notification template for "+mailType+" is not defined.");
580-
if (!mail.getSend()) throw new RegistrarException("Sending of notification "+mailType+" is disabled.");
579+
if (mail == null) throw new RegistrarException("Notification template for "+mailType+" for application " + app.getId() + " is not defined.");
580+
if (!mail.getSend()) throw new RegistrarException("Sending of notification "+mailType+" for application " + app.getId() + " is disabled.");
581581

582582
if (!(AuthzResolver.hasRole(sess.getPerunPrincipal(), Role.PERUNADMIN) || AuthzResolver.hasRole(sess.getPerunPrincipal(), Role.PERUNADMINBA))) {
583583
if (MailType.APP_ERROR_VO_ADMIN.equals(mailType)) {
584-
throw new RegistrarException("APP_ERROR_VO_ADMIN notification can't be sent this way, since it's bound to each approval process. Try to approve application once again to receive this message.");
584+
throw new RegistrarException("APP_ERROR_VO_ADMIN notification can't be sent this way, since it's bound to each approval process. Try to approve application " + app.getId() + " once again to receive this message.");
585585
}
586586

587587
switch (mailType) {
@@ -591,28 +591,28 @@ public void sendMessage(PerunSession sess, Application app, MailType mailType, S
591591
if (app.getState().equals(Application.AppState.NEW) || app.getState().equals(Application.AppState.VERIFIED)) {
592592
sendMessage(app, mailType, null, null);
593593
} else {
594-
throw new RegistrarException("Application must be in state NEW or VERIFIED to allow sending of "+mailType+" notification.");
594+
throw new RegistrarException("Application " + app.getId() + " must be in state NEW or VERIFIED to allow sending of "+mailType+" notification.");
595595
}
596596
} break;
597597
case MAIL_VALIDATION: {
598598
if (app.getState().equals(Application.AppState.NEW)) {
599599
sendMessage(app, mailType, null, null);
600600
} else {
601-
throw new ApplicationNotNewException("Application must be in state NEW to allow sending of "+mailType+" notification.", app.getState().toString());
601+
throw new ApplicationNotNewException("Application " + app.getId() + " must be in state NEW to allow sending of "+mailType+" notification.", app.getState().toString());
602602
}
603603
} break;
604604
case APP_APPROVED_USER: {
605605
if (Application.AppState.APPROVED.equals(app.getState())) {
606606
sendMessage(app, mailType, null, null);
607607
} else {
608-
throw new RegistrarException("Application must be in state APPROVED to allow sending of "+mailType+" notification.");
608+
throw new RegistrarException("Application " + app.getId() + " must be in state APPROVED to allow sending of "+mailType+" notification.");
609609
}
610610
} break;
611611
case APP_REJECTED_USER: {
612612
if (Application.AppState.REJECTED.equals(app.getState())) {
613613
sendMessage(app, mailType, reason, null);
614614
} else {
615-
throw new RegistrarException("Application must be in state REJECTED to allow sending of "+mailType+" notification.");
615+
throw new RegistrarException("Application " + app.getId() + " must be in state REJECTED to allow sending of "+mailType+" notification.");
616616
}
617617
} break;
618618
}
@@ -623,6 +623,13 @@ public void sendMessage(PerunSession sess, Application app, MailType mailType, S
623623
perun.getAuditer().log(sess, new MailSentForApplication(mailType, app.getId()));
624624
}
625625

626+
@Override
627+
public void sendMessages(PerunSession sess, List<Application> applications, MailType mailType, String reason) throws PerunException {
628+
for (Application application : applications) {
629+
sendMessage(sess, application, mailType, reason);
630+
}
631+
}
632+
626633
@Override
627634
public void sendInvitation(PerunSession sess, Vo vo, Group group, String name, String email, String language) throws PerunException {
628635
perun.getVosManagerBl().checkVoExists(sess, vo);

perun-registrar-lib/src/test/java/cz/metacentrum/perun/registrar/RegistrarBaseIntegrationTest.java

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,14 @@
3939
import org.junit.Test;
4040
import org.junit.runner.RunWith;
4141
import org.springframework.beans.factory.annotation.Autowired;
42-
import org.springframework.dao.DataIntegrityViolationException;
42+
import org.springframework.mail.javamail.JavaMailSender;
4343
import org.springframework.test.context.ContextConfiguration;
4444
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
4545
import org.springframework.test.util.AopTestUtils;
46+
import org.springframework.test.util.ReflectionTestUtils;
4647
import org.springframework.transaction.annotation.Transactional;
4748

49+
import javax.mail.internet.MimeMessage;
4850
import java.util.*;
4951
import java.util.function.Predicate;
5052

@@ -54,6 +56,10 @@
5456
import static org.assertj.core.api.Assertions.assertThat;
5557
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
5658
import static org.junit.Assert.*;
59+
import static org.mockito.ArgumentMatchers.any;
60+
import static org.mockito.Mockito.spy;
61+
import static org.mockito.Mockito.times;
62+
import static org.mockito.Mockito.verify;
5763

5864
/**
5965
* Base registrar-lib test class
@@ -266,6 +272,45 @@ public void updateAppMailMessageTemplates() throws PerunException {
266272
assertEquals("Html message (cs) doesn't contain correct text", mail.getHtmlMessage(new Locale("cs")).getText(), "<p>Upravený český text mailu <b>v html</b>.</p>");
267273
}
268274

275+
@Test
276+
public void testResendNotifications() throws PerunException {
277+
JavaMailSender mailSender = (JavaMailSender) ReflectionTestUtils.getField(mailManager, "mailSender");
278+
assert mailSender != null;
279+
JavaMailSender spyMailSender = spy(mailSender);
280+
ReflectionTestUtils.setField(mailManager, "mailSender", spyMailSender);
281+
282+
User user1 = new User(-1, "User1", "Test1", "", "", "");
283+
User user2 = new User(-2, "User2", "Test2", "", "", "");
284+
User user3 = new User(-3, "User3", "Test3", "", "", "");
285+
user1 = perun.getUsersManagerBl().createUser(session, user1);
286+
user2 = perun.getUsersManagerBl().createUser(session, user2);
287+
user3 = perun.getUsersManagerBl().createUser(session, user3);
288+
289+
Application application1 = prepareApplicationToVo(user1);
290+
Application application2 = prepareApplicationToVo(user2);
291+
Application application3 = prepareApplicationToVo(user3);
292+
registrarManager.submitApplication(session, application1, new ArrayList<>());
293+
registrarManager.submitApplication(session, application2, new ArrayList<>());
294+
registrarManager.submitApplication(session, application3, new ArrayList<>());
295+
296+
application1.setState(Application.AppState.REJECTED);
297+
application2.setState(Application.AppState.REJECTED);
298+
application3.setState(Application.AppState.REJECTED);
299+
300+
ApplicationForm form = registrarManager.getFormForVo(vo);
301+
302+
ApplicationMail mail = new ApplicationMail(0,AppType.INITIAL, form.getId(), MailType.APP_REJECTED_USER, true);
303+
MailText t = mail.getMessage(new Locale("en"));
304+
t.setSubject("Test subject");
305+
t.setText("Test Mail content.");
306+
mailManager.addMail(session, form, mail);
307+
308+
309+
mailManager.sendMessages(session, List.of(application1, application2, application3), MailType.APP_REJECTED_USER, null);
310+
311+
verify(spyMailSender, times(3)).send(any(MimeMessage.class));
312+
}
313+
269314
@Test
270315
public void createVOformIntegrationTest() throws PerunException {
271316
System.out.println("createVOformIntegrationTest()");

perun-rpc/src/main/java/cz/metacentrum/perun/rpc/methods/RegistrarManagerMethod.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,40 @@ public Void call(ApiCaller ac, Deserializer parms) throws PerunException {
281281

282282
}
283283

284+
},
285+
286+
/*#
287+
* Manually re-send multiple notifications at once.
288+
* Expected to be called as a result of direct VO administrator action in the web UI.
289+
*
290+
* @param ids int[] List of Application IDs
291+
*/
292+
sendMessages {
293+
294+
@Override
295+
public Void call(ApiCaller ac, Deserializer parms) throws PerunException {
296+
parms.stateChangingCheck();
297+
298+
List<Application> applications = new ArrayList<>();
299+
List<Integer> appIds = parms.readList("ids", Integer.class);
300+
for (Integer id : appIds) {
301+
applications.add(ac.getRegistrarManager().getApplicationById(ac.getSession(), id));
302+
}
303+
if (parms.readString("mailType").equals("APP_REJECTED_USER")) {
304+
305+
ac.getRegistrarManager().getMailManager().sendMessages(ac.getSession(), applications,
306+
ApplicationMail.MailType.valueOf(parms.readString("mailType")),
307+
parms.readString("reason"));
308+
309+
} else {
310+
311+
ac.getRegistrarManager().getMailManager().sendMessages(ac.getSession(), applications,
312+
ApplicationMail.MailType.valueOf(parms.readString("mailType")), null);
313+
314+
}
315+
return null;
316+
}
317+
284318
},
285319
/*#
286320
* Create application form for a VO.

0 commit comments

Comments
 (0)