Skip to content

Commit

Permalink
feat(core): approve applications method
Browse files Browse the repository at this point in the history
Added bulk method for approving multiple applications at once.
  • Loading branch information
sarkapalkovicova committed Sep 3, 2023
1 parent bcf8900 commit 6fdaf33
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 11 deletions.
16 changes: 16 additions & 0 deletions perun-openapi/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16341,6 +16341,22 @@ paths:
default:
$ref: '#/components/responses/ExceptionResponse'

/urlinjsonout/registrarManager/approveApplications:
post:
tags:
- RegistrarManager
operationId: approveApplications
summary: Manually approves 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'
responses:
'200':
$ref: '#/components/responses/VoidResponse'
default:
$ref: '#/components/responses/ExceptionResponse'

/urlinjsonout/registrarManager/rejectApplication:
post:
tags:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,15 @@ public interface RegistrarManager {
*/
Application approveApplication(PerunSession session, int appId) throws PerunException;

/**
* Manually approves 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
* @throws PerunException
*/
void approveApplications(PerunSession sess, List<Integer> applicationIds) throws PerunException;

/**
* Approves an application in one transaction.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1753,7 +1753,7 @@ private void deleteApplicationReservedLogins(PerunSession sess, Application app)
public Application approveApplication(PerunSession sess, int appId) throws PerunException {
synchronized(runningApproveApplication) {
if (runningApproveApplication.contains(appId)) {
throw new AlreadyProcessingException("Application approval is already processing.");
throw new AlreadyProcessingException("Application " + appId + " approval is already processing.");
} else {
runningApproveApplication.add(appId);
}
Expand All @@ -1764,13 +1764,13 @@ public Application approveApplication(PerunSession sess, int appId) throws Perun
app = registrarManager.approveApplicationInternal(sess, appId);
} catch (AlreadyMemberException ex) {
// case when user joined identity after sending initial application and former user was already member of VO
throw new RegistrarException("User is already member (with ID: "+ex.getMember().getId()+") of your VO/group. (user joined his identities after sending new application). You can reject this application and re-validate old member to keep old data (e.g. login,email).", ex);
throw new RegistrarException("User is already member (with ID: "+ex.getMember().getId()+") of your VO/group. (user joined his identities after sending new application). You can reject this application " + appId + " and re-validate old member to keep old data (e.g. login,email).", ex);
} catch (MemberNotExistsException ex) {
throw new RegistrarException("To approve application user must already be member of VO.", ex);
throw new RegistrarException("To approve application " + appId + " user must already be member of VO.", ex);
} catch (NotGroupMemberException ex) {
throw new RegistrarException("To approve application user must already be member of Group.", ex);
throw new RegistrarException("To approve application " + appId + " user must already be member of Group.", ex);
} catch (UserNotExistsException | UserExtSourceNotExistsException | ExtSourceNotExistsException ex) {
throw new RegistrarException("User specified by the data in application was not found. If you tried to approve application for the Group, try to check, if user already has approved application in the VO. Application to the VO must be approved first.", ex);
throw new RegistrarException("User specified by the data in application " + appId + " was not found. If you tried to approve application for the Group, try to check, if user already has approved application in the VO. Application to the VO must be approved first.", ex);
} finally {
synchronized (runningApproveApplication) {
runningApproveApplication.remove(appId);
Expand Down Expand Up @@ -1821,6 +1821,13 @@ public Application approveApplication(PerunSession sess, int appId) throws Perun
return app;
}

@Override
public void approveApplications(PerunSession sess, List<Integer> applicationIds) throws PerunException {
for (Integer id : applicationIds) {
approveApplication(sess, id);
}
}

/**
* Returns list of all groups embedded to target vo/group of application
* @param sess
Expand Down Expand Up @@ -1941,7 +1948,7 @@ private void submitEmbeddedGroupApplications(PerunSession sess, List<Group> grou
public Application approveApplicationInternal(PerunSession sess, int appId) 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.");
Member member;

//Authorization
Expand All @@ -1957,9 +1964,9 @@ public Application approveApplicationInternal(PerunSession sess, int appId) thro

// only VERIFIED applications can be approved
if (!AppState.VERIFIED.equals(app.getState())) {
if (AppState.APPROVED.equals(app.getState())) throw new RegistrarException("Application is already approved. Try to refresh the view to see changes.");
if (AppState.REJECTED.equals(app.getState())) throw new RegistrarException("Rejected application cant' be approved. Try to refresh the view to see changes.");
throw new RegistrarException("User didn't verify his email address yet. Please wait until application will be in a 'Submitted' state. You can send mail verification notification to user again if you wish.");
if (AppState.APPROVED.equals(app.getState())) throw new RegistrarException("Application " + appId + " is already approved. Try to refresh the view to see changes.");
if (AppState.REJECTED.equals(app.getState())) throw new RegistrarException("Rejected application " + appId + " cant' be approved. Try to refresh the view to see changes.");
throw new RegistrarException("User didn't verify his email address yet. Please wait until application " + appId + " will be in a 'Submitted' state. You can send mail verification notification to user again if you wish.");
}

LinkedHashMap<String, String> additionalAttributes = BeansUtils.stringToMapOfAttributes(app.getFedInfo());
Expand Down Expand Up @@ -2028,7 +2035,7 @@ public Application approveApplicationInternal(PerunSession sess, int appId) thro
// and we don't want to validate expired, suspended or disabled users without VO admin owns action !!
// meaning, user should submit membership extension application first !!
if (!Arrays.asList(Status.VALID, Status.INVALID).contains(member.getStatus())) {
throw new CantBeApprovedException("Application of member with membership status: "+member.getStatus()+" can't be approved. Please wait until member extends/re-validate own membership in a VO.");
throw new CantBeApprovedException("Application " + appId + " of member with membership status: "+member.getStatus()+" can't be approved. Please wait until member extends/re-validate own membership in a VO.");
}

// store all attributes (but not logins)
Expand Down Expand Up @@ -2164,7 +2171,7 @@ public Application approveApplicationInternal(PerunSession sess, int appId) thro
// and we don't want to validate expired, suspended or disabled users without VO admin owns action !!
// meaning, user should submit membership extension application first !!
if (!Arrays.asList(Status.VALID, Status.INVALID).contains(member.getStatus())) {
throw new CantBeApprovedException("Application of member with membership status: "+member.getStatus()+" can't be approved. Please wait until member extends/re-validate own membership in a VO.");
throw new CantBeApprovedException("Application " + appId + " of member with membership status: "+member.getStatus()+" can't be approved. Please wait until member extends/re-validate own membership in a VO.");
}

// overwrite member with group context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1120,6 +1120,24 @@ public void testEmbeddedGroupsSubmission() throws PerunException {
assertEquals(1, registrarManager.getApplicationsForGroup(session, group2, List.of("NEW", "VERIFIED")).size());
}

@Test
public void testApproveApplications() 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);
Application application2 = prepareApplicationToVo(user2);
registrarManager.submitApplication(session, application1, new ArrayList<>());
registrarManager.submitApplication(session, application2, new ArrayList<>());

registrarManager.approveApplications(session, List.of(application1.getId(), application2.getId()));

List<Integer> 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 testEmbeddedGroupsSubmission_groupAutoApprove() throws PerunException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,23 @@ public Application call(ApiCaller ac, Deserializer parms) throws PerunException

},

/*#
* Manually approve 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
*/
approveApplications {

@Override
public Void call(ApiCaller ac, Deserializer parms) throws PerunException {
parms.stateChangingCheck();
ac.getRegistrarManager().approveApplications(ac.getSession(), parms.readList("ids", Integer.class));
return null;
}

},

/*#
* Check if application can be approved based on form module rules. Throws exception if not.
* Expected to be called from Web UI before actual approving happens, so VO admin
Expand Down

0 comments on commit 6fdaf33

Please sign in to comment.