applications, MailType mailType, String reason) throws PerunException {
+ for (Application application : applications) {
+ sendMessage(sess, application, mailType, reason);
+ }
+ }
+
@Override
public void sendInvitation(PerunSession sess, Vo vo, Group group, String name, String email, String language) throws PerunException {
perun.getVosManagerBl().checkVoExists(sess, vo);
diff --git a/perun-registrar-lib/src/test/java/cz/metacentrum/perun/registrar/RegistrarBaseIntegrationTest.java b/perun-registrar-lib/src/test/java/cz/metacentrum/perun/registrar/RegistrarBaseIntegrationTest.java
index d3f357e0ba..3376dcdcf8 100644
--- a/perun-registrar-lib/src/test/java/cz/metacentrum/perun/registrar/RegistrarBaseIntegrationTest.java
+++ b/perun-registrar-lib/src/test/java/cz/metacentrum/perun/registrar/RegistrarBaseIntegrationTest.java
@@ -39,12 +39,14 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.util.AopTestUtils;
+import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.transaction.annotation.Transactional;
+import javax.mail.internet.MimeMessage;
import java.util.*;
import java.util.function.Predicate;
@@ -54,6 +56,10 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.Assert.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
/**
* Base registrar-lib test class
@@ -266,6 +272,45 @@ public void updateAppMailMessageTemplates() throws PerunException {
assertEquals("Html message (cs) doesn't contain correct text", mail.getHtmlMessage(new Locale("cs")).getText(), "Upravený český text mailu v html.
");
}
+ @Test
+ public void testResendNotifications() throws PerunException {
+ JavaMailSender mailSender = (JavaMailSender) ReflectionTestUtils.getField(mailManager, "mailSender");
+ assert mailSender != null;
+ JavaMailSender spyMailSender = spy(mailSender);
+ ReflectionTestUtils.setField(mailManager, "mailSender", spyMailSender);
+
+ User user1 = new User(-1, "User1", "Test1", "", "", "");
+ User user2 = new User(-2, "User2", "Test2", "", "", "");
+ User user3 = new User(-3, "User3", "Test3", "", "", "");
+ user1 = perun.getUsersManagerBl().createUser(session, user1);
+ user2 = perun.getUsersManagerBl().createUser(session, user2);
+ user3 = perun.getUsersManagerBl().createUser(session, user3);
+
+ Application application1 = prepareApplicationToVo(user1);
+ Application application2 = prepareApplicationToVo(user2);
+ Application application3 = prepareApplicationToVo(user3);
+ registrarManager.submitApplication(session, application1, new ArrayList<>());
+ registrarManager.submitApplication(session, application2, new ArrayList<>());
+ registrarManager.submitApplication(session, application3, new ArrayList<>());
+
+ application1.setState(Application.AppState.REJECTED);
+ application2.setState(Application.AppState.REJECTED);
+ application3.setState(Application.AppState.REJECTED);
+
+ ApplicationForm form = registrarManager.getFormForVo(vo);
+
+ ApplicationMail mail = new ApplicationMail(0,AppType.INITIAL, form.getId(), MailType.APP_REJECTED_USER, true);
+ MailText t = mail.getMessage(new Locale("en"));
+ t.setSubject("Test subject");
+ t.setText("Test Mail content.");
+ mailManager.addMail(session, form, mail);
+
+
+ mailManager.sendMessages(session, List.of(application1, application2, application3), MailType.APP_REJECTED_USER, null);
+
+ verify(spyMailSender, times(3)).send(any(MimeMessage.class));
+ }
+
@Test
public void createVOformIntegrationTest() throws PerunException {
System.out.println("createVOformIntegrationTest()");
diff --git a/perun-rpc/src/main/java/cz/metacentrum/perun/rpc/methods/RegistrarManagerMethod.java b/perun-rpc/src/main/java/cz/metacentrum/perun/rpc/methods/RegistrarManagerMethod.java
index fa79237f83..6b994720c1 100644
--- a/perun-rpc/src/main/java/cz/metacentrum/perun/rpc/methods/RegistrarManagerMethod.java
+++ b/perun-rpc/src/main/java/cz/metacentrum/perun/rpc/methods/RegistrarManagerMethod.java
@@ -281,6 +281,40 @@ public Void call(ApiCaller ac, Deserializer parms) throws PerunException {
}
+ },
+
+ /*#
+ * Manually re-send multiple notifications at once.
+ * Expected to be called as a result of direct VO administrator action in the web UI.
+ *
+ * @param ids int[] List of Application IDs
+ */
+ sendMessages {
+
+ @Override
+ public Void call(ApiCaller ac, Deserializer parms) throws PerunException {
+ parms.stateChangingCheck();
+
+ List applications = new ArrayList<>();
+ List appIds = parms.readList("ids", Integer.class);
+ for (Integer id : appIds) {
+ applications.add(ac.getRegistrarManager().getApplicationById(ac.getSession(), id));
+ }
+ if (parms.readString("mailType").equals("APP_REJECTED_USER")) {
+
+ ac.getRegistrarManager().getMailManager().sendMessages(ac.getSession(), applications,
+ ApplicationMail.MailType.valueOf(parms.readString("mailType")),
+ parms.readString("reason"));
+
+ } else {
+
+ ac.getRegistrarManager().getMailManager().sendMessages(ac.getSession(), applications,
+ ApplicationMail.MailType.valueOf(parms.readString("mailType")), null);
+
+ }
+ return null;
+ }
+
},
/*#
* Create application form for a VO.
From e43e01b5db11cf8272ec8234fd0b7332ad82aaeb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ou=C5=A1ek?=
Date: Tue, 5 Sep 2023 08:44:25 +0200
Subject: [PATCH 08/10] ci: fix sections in upgrade notes
---
.releaserc.json | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/.releaserc.json b/.releaserc.json
index fe5a95507e..a18f113e76 100644
--- a/.releaserc.json
+++ b/.releaserc.json
@@ -22,46 +22,53 @@
"types": [
{
"type": "feat",
- "hidden": false
+ "section":"Features"
},
{
"type": "fix",
- "hidden": false
+ "section": "Bug Fixes"
},
{
"type": "perf",
- "hidden": false
+ "section": "Performance Improvements"
},
{
"type": "revert",
- "hidden": false
+ "section": "Reverts"
},
{
"type": "docs",
+ "section": "Documentation",
"hidden": true
},
{
"type": "style",
+ "section": "Code style",
"hidden": true
},
{
"type": "chore",
+ "section": "Others",
"hidden": true
},
{
"type": "refactor",
+ "section": "Refactoring",
"hidden": true
},
{
"type": "test",
+ "section": "Tests",
"hidden": true
},
{
"type": "build",
+ "section": "Build",
"hidden": true
},
{
"type": "ci",
+ "section": "CI",
"hidden": true
}
],
From 019acfe3f7cbb5c7ffa876782be7f1535337f773 Mon Sep 17 00:00:00 2001
From: sarkapalkovicova
Date: Wed, 6 Sep 2023 13:27:41 +0200
Subject: [PATCH 09/10] fix(core): approve applications order
Sort application before approving.
First, approve applications to VOs and then to groups.
---
.../registrar/impl/RegistrarManagerImpl.java | 2 ++
.../RegistrarBaseIntegrationTest.java | 24 ++++++++++++++++++-
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/perun-registrar-lib/src/main/java/cz/metacentrum/perun/registrar/impl/RegistrarManagerImpl.java b/perun-registrar-lib/src/main/java/cz/metacentrum/perun/registrar/impl/RegistrarManagerImpl.java
index 7964060897..7d2804aa68 100644
--- a/perun-registrar-lib/src/main/java/cz/metacentrum/perun/registrar/impl/RegistrarManagerImpl.java
+++ b/perun-registrar-lib/src/main/java/cz/metacentrum/perun/registrar/impl/RegistrarManagerImpl.java
@@ -1829,7 +1829,9 @@ public Application approveApplication(PerunSession sess, int appId) throws Perun
}
@Override
+ @Transactional(rollbackFor = Exception.class)
public void approveApplications(PerunSession sess, List applicationIds) throws PerunException {
+ Collections.sort(applicationIds);
for (Integer id : applicationIds) {
approveApplication(sess, id);
}
diff --git a/perun-registrar-lib/src/test/java/cz/metacentrum/perun/registrar/RegistrarBaseIntegrationTest.java b/perun-registrar-lib/src/test/java/cz/metacentrum/perun/registrar/RegistrarBaseIntegrationTest.java
index eb46e7b6f2..2dceef104a 100644
--- a/perun-registrar-lib/src/test/java/cz/metacentrum/perun/registrar/RegistrarBaseIntegrationTest.java
+++ b/perun-registrar-lib/src/test/java/cz/metacentrum/perun/registrar/RegistrarBaseIntegrationTest.java
@@ -1132,13 +1132,35 @@ public void testApproveApplications() throws PerunException {
registrarManager.submitApplication(session, application1, new ArrayList<>());
registrarManager.submitApplication(session, application2, new ArrayList<>());
- registrarManager.approveApplications(session, List.of(application1.getId(), application2.getId()));
+ registrarManager.approveApplications(session, new ArrayList<>(Arrays.asList(application1.getId(), application2.getId())));
List approvedAppIds = registrarManager.getApplicationsForVo(session, vo, List.of("APPROVED"), false).stream().map(Application::getId).toList();
assertEquals(2, approvedAppIds.size());
assertThat(approvedAppIds).containsOnly(application1.getId(), application2.getId());
}
+ @Test
+ public void testApproveApplicationsOrder() throws PerunException {
+ User user = new User(1, "User1", "Test1", "", "", "");
+ user = perun.getUsersManagerBl().createUser(session, user);
+
+ Group group = new Group("Test", "Test group");
+ perun.getGroupsManagerBl().createGroup(session, vo, group);
+ registrarManager.createApplicationFormInGroup(session, group);
+
+ Application applicationToVo = prepareApplicationToVo(user);
+ applicationToVo = registrarManager.submitApplication(session, applicationToVo, new ArrayList<>());
+
+ Application applicationToGroup = prepareApplicationToGroup(user, group);
+ applicationToGroup = registrarManager.submitApplication(session, applicationToGroup, new ArrayList<>());
+
+ registrarManager.approveApplications(session, new ArrayList<>(Arrays.asList(applicationToGroup.getId(), applicationToVo.getId())));
+
+ List approvedAppIds = registrarManager.getApplicationsForVo(session, vo, List.of("APPROVED"), true).stream().map(Application::getId).toList();
+ assertEquals(2, approvedAppIds.size());
+ assertThat(approvedAppIds).containsOnly(applicationToVo.getId(), applicationToGroup.getId());
+ }
+
@Test
public void testEmbeddedGroupsSubmission_groupAutoApprove() throws PerunException {
GroupsManager groupsManager = perun.getGroupsManager();
From a2d270c0b5b24202a854185cad072be74acc151b Mon Sep 17 00:00:00 2001
From: sarkapalkovicova
Date: Sun, 3 Sep 2023 20:38:24 +0200
Subject: [PATCH 10/10] feat(core): reject applications method
Added bulk method for rejecting multiple applications at once.
---
perun-openapi/openapi.yml | 17 ++++++++
.../perun/registrar/RegistrarManager.java | 10 +++++
.../registrar/impl/RegistrarManagerImpl.java | 17 ++++++--
.../RegistrarBaseIntegrationTest.java | 41 +++++++++++++++++++
.../rpc/methods/RegistrarManagerMethod.java | 29 +++++++++++++
5 files changed, 110 insertions(+), 4 deletions(-)
diff --git a/perun-openapi/openapi.yml b/perun-openapi/openapi.yml
index dbdbed33e1..455f357990 100644
--- a/perun-openapi/openapi.yml
+++ b/perun-openapi/openapi.yml
@@ -16371,6 +16371,23 @@ paths:
default:
$ref: '#/components/responses/ExceptionResponse'
+ /urlinjsonout/registrarManager/rejectApplications:
+ post:
+ tags:
+ - RegistrarManager
+ operationId: rejectApplications
+ summary: Manually rejects multiple applications at once.
+ description: |
+ Expected to be called as a result of direct VO administrator action in the web UI.
+ parameters:
+ - $ref: '#/components/parameters/ids'
+ - { name: reason, schema: { type: string }, in: query, description: "description of reason", required: false }
+ responses:
+ '200':
+ $ref: '#/components/responses/VoidResponse'
+ default:
+ $ref: '#/components/responses/ExceptionResponse'
+
/urlinjsonout/registrarManager/deleteApplication:
post:
tags:
diff --git a/perun-registrar-lib/src/main/java/cz/metacentrum/perun/registrar/RegistrarManager.java b/perun-registrar-lib/src/main/java/cz/metacentrum/perun/registrar/RegistrarManager.java
index b0bb824dc7..6032cbfdfc 100644
--- a/perun-registrar-lib/src/main/java/cz/metacentrum/perun/registrar/RegistrarManager.java
+++ b/perun-registrar-lib/src/main/java/cz/metacentrum/perun/registrar/RegistrarManager.java
@@ -403,6 +403,16 @@ public interface RegistrarManager {
*/
Application rejectApplication(PerunSession session, int appId, String reason) throws PerunException;
+ /**
+ * Manually rejects multiple applications at once. Expected to be called as a result of direct VO administrator action in the web UI.
+ *
+ * @param sess perun session
+ * @param applicationIds list of application IDs
+ * @param reason optional reason of rejection displayed to user
+ * @throws PerunException
+ */
+ void rejectApplications(PerunSession sess, List applicationIds, String reason) throws PerunException;
+
/**
* Returns data submitted by user in given application (by id)
*
diff --git a/perun-registrar-lib/src/main/java/cz/metacentrum/perun/registrar/impl/RegistrarManagerImpl.java b/perun-registrar-lib/src/main/java/cz/metacentrum/perun/registrar/impl/RegistrarManagerImpl.java
index d232f4e2bb..112e107b81 100644
--- a/perun-registrar-lib/src/main/java/cz/metacentrum/perun/registrar/impl/RegistrarManagerImpl.java
+++ b/perun-registrar-lib/src/main/java/cz/metacentrum/perun/registrar/impl/RegistrarManagerImpl.java
@@ -1634,7 +1634,7 @@ public Application verifyApplication(PerunSession sess, int appId) throws PerunE
public Application rejectApplication(PerunSession sess, int appId, String reason) throws PerunException {
Application app = getApplicationById(appId);
- if (app == null) throw new RegistrarException("Application with ID="+appId+" doesn't exists.");
+ if (app == null) throw new RegistrarException("Application with ID=" + appId + " doesn't exists.");
//Authorization
if (app.getGroup() == null) {
@@ -1649,15 +1649,15 @@ public Application rejectApplication(PerunSession sess, int appId, String reason
// only VERIFIED applications can be rejected
if (AppState.APPROVED.equals(app.getState())) {
- throw new RegistrarException("Approved application can't be rejected ! Try to refresh the view to see changes.");
+ throw new RegistrarException("Approved application " + appId + " can't be rejected ! Try to refresh the view to see changes.");
} else if (AppState.REJECTED.equals(app.getState())) {
- throw new RegistrarException("Application is already rejected. Try to refresh the view to see changes.");
+ throw new RegistrarException("Application " + appId + " is already rejected. Try to refresh the view to see changes.");
}
// lock to prevent concurrent runs
synchronized(runningRejectApplication) {
if (runningRejectApplication.contains(appId)) {
- throw new AlreadyProcessingException("Application rejection is already processing.");
+ throw new AlreadyProcessingException("Application " + appId + " rejection is already processing.");
} else {
runningRejectApplication.add(appId);
}
@@ -1724,6 +1724,15 @@ public Application rejectApplication(PerunSession sess, int appId, String reason
}
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void rejectApplications(PerunSession sess, List applicationIds, String reason) throws PerunException {
+ Collections.sort(applicationIds, Collections.reverseOrder());
+ for (Integer id : applicationIds) {
+ rejectApplication(sess, id, reason);
+ }
+ }
+
/**
* Deletes reserved logins which are used only by the given application.
* Deletes them from both KDC and DB.
diff --git a/perun-registrar-lib/src/test/java/cz/metacentrum/perun/registrar/RegistrarBaseIntegrationTest.java b/perun-registrar-lib/src/test/java/cz/metacentrum/perun/registrar/RegistrarBaseIntegrationTest.java
index d3f357e0ba..7e5ec3186d 100644
--- a/perun-registrar-lib/src/test/java/cz/metacentrum/perun/registrar/RegistrarBaseIntegrationTest.java
+++ b/perun-registrar-lib/src/test/java/cz/metacentrum/perun/registrar/RegistrarBaseIntegrationTest.java
@@ -1259,6 +1259,47 @@ public void testRejectApplicationsAfterMemberRemoval() throws PerunException {
assertEquals(1, group1Apps.size());
}
+ @Test
+ public void testRejectApplications() throws PerunException {
+ User user1 = new User(1, "User1", "Test1", "", "", "");
+ User user2 = new User(2, "User2", "Test2", "", "", "");
+ user1 = perun.getUsersManagerBl().createUser(session, user1);
+ user2 = perun.getUsersManagerBl().createUser(session, user2);
+
+ Application application1 = prepareApplicationToVo(user1);
+ application1 = registrarManager.submitApplication(session, application1, new ArrayList<>());
+
+ Application application2 = prepareApplicationToVo(user2);
+ application2.setCreatedBy("perunTests2");
+ application2 = registrarManager.submitApplication(session, application2, new ArrayList<>());
+
+ registrarManager.rejectApplications(session, new ArrayList<>(Arrays.asList(application1.getId(), application2.getId())), null);
+
+ List rejectedAppIdsVO = registrarManager.getApplicationsForVo(session, vo, List.of("REJECTED"), false).stream().map(Application::getId).toList();
+ assertThat(rejectedAppIdsVO).containsOnly(application1.getId(), application2.getId());
+ }
+
+ @Test
+ public void testRejectApplicationsOrder() throws PerunException {
+ User user = new User(1, "User1", "Test1", "", "", "");
+ user = perun.getUsersManagerBl().createUser(session, user);
+
+ Group group = new Group("Test", "Test group");
+ perun.getGroupsManagerBl().createGroup(session, vo, group);
+ registrarManager.createApplicationFormInGroup(session, group);
+
+ Application applicationToVo = prepareApplicationToVo(user);
+ applicationToVo = registrarManager.submitApplication(session, applicationToVo, new ArrayList<>());
+
+ Application applicationToGroup = prepareApplicationToGroup(user, group);
+ applicationToGroup = registrarManager.submitApplication(session, applicationToGroup, new ArrayList<>());
+
+ registrarManager.rejectApplications(session, new ArrayList<>(Arrays.asList(applicationToVo.getId(), applicationToGroup.getId())), null);
+
+ List rejectedAppIds = registrarManager.getApplicationsForVo(session, vo, List.of("REJECTED"), true).stream().map(Application::getId).toList();
+ assertThat(rejectedAppIds).containsOnly(applicationToVo.getId(), applicationToGroup.getId());
+ }
+
private Application prepareApplicationToVo(User user) {
Application application = new Application();
application.setVo(vo);
diff --git a/perun-rpc/src/main/java/cz/metacentrum/perun/rpc/methods/RegistrarManagerMethod.java b/perun-rpc/src/main/java/cz/metacentrum/perun/rpc/methods/RegistrarManagerMethod.java
index fa79237f83..1b8c06704f 100644
--- a/perun-rpc/src/main/java/cz/metacentrum/perun/rpc/methods/RegistrarManagerMethod.java
+++ b/perun-rpc/src/main/java/cz/metacentrum/perun/rpc/methods/RegistrarManagerMethod.java
@@ -908,6 +908,35 @@ public Application call(ApiCaller ac, Deserializer parms) throws PerunException
},
+ /*#
+ * Manually rejects multiple applications at once.
+ * Expected to be called as a result of direct VO administrator action in the web UI.
+ *
+ * @param ids int[] List of Application IDs
+ */
+ /*#
+ * Manually rejects multiple applications at once with a reason.
+ * Expected to be called as a result of direct VO administrator action in the web UI.
+ *
+ * @param ids int[] List of Application IDs
+ * @param reason String Reason description
+ */
+ rejectApplications {
+
+ @Override
+ public Application call(ApiCaller ac, Deserializer parms) throws PerunException {
+ parms.stateChangingCheck();
+
+ if (parms.contains("reason")) {
+ ac.getRegistrarManager().rejectApplications(ac.getSession(), parms.readList("ids", Integer.class), parms.readString("reason"));
+ } else {
+ ac.getRegistrarManager().rejectApplications(ac.getSession(), parms.readList("ids", Integer.class), null);
+ }
+
+ return null;
+ }
+ },
+
/*#
* Forcefully marks application as verified
* (only when application was in NEW state)