Skip to content

Commit 3be4958

Browse files
committed
UY-1409 fix bulk invitation with a user that is a member.
1 parent 63ac3fa commit 3be4958

File tree

6 files changed

+102
-19
lines changed

6 files changed

+102
-19
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright (c) 2021 Bixbit - Krzysztof Benedyczak. All rights reserved.
3+
* See LICENCE.txt file for licensing information.
4+
*/
5+
6+
package pl.edu.icm.unity.engine.api.project;
7+
8+
import java.util.Set;
9+
import java.util.Collections;
10+
11+
public class ProjectAddInvitationResult
12+
{
13+
public final Set<String> projectAlreadyMemberEmails;
14+
15+
private ProjectAddInvitationResult(Builder builder)
16+
{
17+
this.projectAlreadyMemberEmails = builder.projectAlreadyMemberEmails;
18+
}
19+
20+
public static Builder builder()
21+
{
22+
return new Builder();
23+
}
24+
25+
public static final class Builder
26+
{
27+
private Set<String> projectAlreadyMemberEmails = Collections.emptySet();
28+
29+
private Builder()
30+
{
31+
}
32+
33+
public Builder withProjectAlreadyMemberEmails(Set<String> projectAlreadyMemberEmails)
34+
{
35+
this.projectAlreadyMemberEmails = projectAlreadyMemberEmails;
36+
return this;
37+
}
38+
39+
public ProjectAddInvitationResult build()
40+
{
41+
return new ProjectAddInvitationResult(this);
42+
}
43+
}
44+
45+
46+
}

engine-api/src/main/java/pl/edu/icm/unity/engine/api/project/ProjectInvitationsManagement.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*/
1717
public interface ProjectInvitationsManagement
1818
{
19-
void addInvitations(Set<ProjectInvitationParam> param) throws EngineException;
19+
ProjectAddInvitationResult addInvitations(Set<ProjectInvitationParam> param) throws EngineException;
2020

2121
/**
2222
* Gets all project invitations

engine/src/main/java/pl/edu/icm/unity/engine/project/ProjectInvitationsManagementImpl.java

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.util.ArrayList;
1212
import java.util.Arrays;
1313
import java.util.Collections;
14+
import java.util.HashSet;
1415
import java.util.List;
1516
import java.util.Map;
1617
import java.util.Optional;
@@ -32,6 +33,7 @@
3233
import pl.edu.icm.unity.engine.api.RegistrationsManagement;
3334
import pl.edu.icm.unity.engine.api.entity.EntityWithContactInfo;
3435
import pl.edu.icm.unity.engine.api.identity.UnknownEmailException;
36+
import pl.edu.icm.unity.engine.api.project.ProjectAddInvitationResult;
3537
import pl.edu.icm.unity.engine.api.project.ProjectInvitation;
3638
import pl.edu.icm.unity.engine.api.project.ProjectInvitationParam;
3739
import pl.edu.icm.unity.engine.api.project.ProjectInvitationsManagement;
@@ -95,7 +97,7 @@ public ProjectInvitationsManagementImpl(@Qualifier("insecure") InvitationManagem
9597
}
9698

9799
@Override
98-
public void addInvitations(Set<ProjectInvitationParam> invitationParams) throws EngineException
100+
public ProjectAddInvitationResult addInvitations(Set<ProjectInvitationParam> invitationParams) throws EngineException
99101
{
100102
for (String project: invitationParams.stream().map(p -> p.project).collect(Collectors.toSet()))
101103
{
@@ -112,32 +114,43 @@ public void addInvitations(Set<ProjectInvitationParam> invitationParams) throws
112114
{
113115
// ok
114116
}
117+
118+
119+
Set<ProjectInvitationParam> toSkip = new HashSet<>();
120+
115121
if (entities != null && !entities.isEmpty())
116122
{
117-
118123
for (ProjectInvitationParam invitation : invitationParams)
119124
{
120-
assertNotMemberAlready(entities.stream()
125+
if (assertNotMemberAlready(entities.stream()
121126
.filter(e -> e.contactEmail.equals(invitation.contactAddress))
122-
.collect(Collectors.toSet()), invitation.project);
127+
.collect(Collectors.toSet()), invitation.project))
128+
{
129+
toSkip.add(invitation);
130+
}
123131
}
124-
125132
}
126-
for (ProjectInvitationParam param : invitationParams)
133+
for (ProjectInvitationParam param : invitationParams.stream().filter(i -> !toSkip.contains(i)).collect(Collectors.toSet()))
127134
{
128135
String code = invitationMan.addInvitation(createComboInvitation(param));
129136
invitationMan.sendInvitation(code);
130137
}
131138

139+
return ProjectAddInvitationResult.builder()
140+
.withProjectAlreadyMemberEmails(toSkip.stream()
141+
.map(a -> a.contactAddress)
142+
.collect(Collectors.toSet()))
143+
.build();
144+
132145
}
133146

134-
private void assertNotMemberAlready(Set<EntityWithContactInfo> collect, String project)
147+
private boolean assertNotMemberAlready(Set<EntityWithContactInfo> collect, String project)
135148
{
136149
if (collect.stream().filter(e -> e.groups.contains(project)).findAny().isPresent())
137150
{
138-
throw new AlreadyMemberException();
151+
return true;
139152
}
140-
153+
return false;
141154
}
142155

143156
private ComboInvitationParam createComboInvitation(ProjectInvitationParam param) throws EngineException

web-upman/src/main/java/io/imunity/upman/front/views/invitations/InvitationsService.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.springframework.stereotype.Service;
1414
import pl.edu.icm.unity.MessageSource;
1515
import pl.edu.icm.unity.base.utils.Log;
16+
import pl.edu.icm.unity.engine.api.project.ProjectAddInvitationResult;
1617
import pl.edu.icm.unity.engine.api.project.ProjectInvitation;
1718
import pl.edu.icm.unity.engine.api.project.ProjectInvitationParam;
1819
import pl.edu.icm.unity.engine.api.project.ProjectInvitationsManagement;
@@ -131,7 +132,14 @@ public void addInvitations(InvitationRequest invitationRequest)
131132

132133
try
133134
{
134-
invitationMan.addInvitations(toAdd);
135+
ProjectAddInvitationResult addInvitations = invitationMan.addInvitations(toAdd);
136+
if (!addInvitations.projectAlreadyMemberEmails.isEmpty())
137+
{
138+
notificationPresenter.showWarning("",
139+
msg.getMessage("InvitationsController.alreadyAMember",
140+
String.join(",", addInvitations.projectAlreadyMemberEmails)));
141+
}
142+
135143
} catch (EngineException | AlreadyMemberException e)
136144
{
137145
log.warn("Can not add invitations", e);

web-upman/src/main/resources/messages/upman/messages.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ InvitationsController.alreadyAMember=User is already a member of the project
138138
InvitationsController.addInvitationError=Can not add invitation
139139
InvitationsController.notAdd=Invitations were not added
140140
InvitationsController.partiallyAdded=Invitations are added only for following emails:{0}
141-
InvitationsController.alreadyAMember=User(s): {0} are already a member of the project
141+
InvitationsController.alreadyAMember=Invitations to user(s): {0} has been skipped, because are already a member of the project.
142142
143143
UpdateRequest.operation=Operation
144144
UpdateRequest.name=Name

web-upman/src/test/java/io/imunity/upman/front/views/invitations/TestInvitationService.java

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
package io.imunity.upman.front.views.invitations;
77

8+
import static org.mockito.ArgumentMatchers.any;
9+
810
import io.imunity.upman.front.model.Group;
911
import io.imunity.upman.front.model.GroupTreeNode;
1012
import io.imunity.upman.front.model.ProjectGroup;
@@ -17,6 +19,7 @@
1719
import org.mockito.Mock;
1820
import org.mockito.junit.jupiter.MockitoExtension;
1921
import pl.edu.icm.unity.MessageSource;
22+
import pl.edu.icm.unity.engine.api.project.ProjectAddInvitationResult;
2023
import pl.edu.icm.unity.engine.api.project.ProjectInvitationParam;
2124
import pl.edu.icm.unity.engine.api.project.ProjectInvitationsManagement;
2225
import pl.edu.icm.unity.exceptions.EngineException;
@@ -31,7 +34,7 @@
3134
import static org.mockito.ArgumentMatchers.eq;
3235
import static org.mockito.Mockito.times;
3336
import static org.mockito.Mockito.verify;
34-
37+
import static org.mockito.Mockito.when;
3538

3639
@ExtendWith(MockitoExtension.class)
3740
public class TestInvitationService
@@ -63,6 +66,8 @@ public void shouldAdd() throws EngineException
6366
ProjectGroup project = new ProjectGroup("/project", "project", "regForm", "singupForm");
6467
Group group = new Group("/", new I18nString("group"), "group", false, false, "", false, 0);
6568
GroupTreeNode node = new GroupTreeNode(group, 0);
69+
when(mockInvitationMan.addInvitations(any())).thenReturn(ProjectAddInvitationResult.builder()
70+
.build());
6671
service.addInvitations(new InvitationRequest(project, List.of("demo@demo.com", "demo2@demo.com"), Set.of(node),
6772
false, expiration));
6873

@@ -71,12 +76,23 @@ public void shouldAdd() throws EngineException
7176
verify(mockInvitationMan, times(1)).addInvitations(argument.capture());
7277

7378
List<Set<ProjectInvitationParam>> arguments = argument.getAllValues();
74-
assertThat(arguments.get(0).size()).isEqualTo(2);
75-
76-
assertThat(arguments.get(0).iterator().next().project).isEqualTo("/project");
77-
assertThat(arguments.get(0).stream().map(p -> p.contactAddress).collect(Collectors.toSet())).isEqualTo(Set.of("demo@demo.com", "demo2@demo.com"));
78-
assertThat(arguments.get(0).iterator().next().groups.iterator().next()).isEqualTo("/");
79-
assertThat(arguments.get(0).iterator().next().expiration).isEqualTo(expiration);
79+
assertThat(arguments.get(0)
80+
.size()).isEqualTo(2);
81+
82+
assertThat(arguments.get(0)
83+
.iterator()
84+
.next().project).isEqualTo("/project");
85+
assertThat(arguments.get(0)
86+
.stream()
87+
.map(p -> p.contactAddress)
88+
.collect(Collectors.toSet())).isEqualTo(Set.of("demo@demo.com", "demo2@demo.com"));
89+
assertThat(arguments.get(0)
90+
.iterator()
91+
.next().groups.iterator()
92+
.next()).isEqualTo("/");
93+
assertThat(arguments.get(0)
94+
.iterator()
95+
.next().expiration).isEqualTo(expiration);
8096
}
8197

8298
@Test

0 commit comments

Comments
 (0)