Implemented #17 and added role removal after deleting members.
Change-Id: I698a194170db7460bde3bbb9db6c20b0dc395975
diff --git a/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java b/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
index f32fb89..1c78ef0 100644
--- a/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
+++ b/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
@@ -84,11 +84,12 @@
// User group and member
public static final int GROUP_MEMBER_EXISTS = 601;
- public static final int GROUP_MEMBER_DELETED = 602;
- public static final int GROUP_MEMBER_NOT_FOUND = 603;
- public static final int INVITATION_EXPIRED = 604;
- public static final int GROUP_NOT_FOUND = 605;
- public static final int GROUP_DELETED = 606;
+ public static final int GROUP_MEMBER_INACTIVE = 602;
+ public static final int GROUP_MEMBER_DELETED = 603;
+ public static final int GROUP_MEMBER_NOT_FOUND = 604;
+ public static final int INVITATION_EXPIRED = 605;
+ public static final int GROUP_NOT_FOUND = 606;
+ public static final int GROUP_DELETED = 607;
// public static final int ARGUMENT_VALIDATION_FAILURE = 700;
diff --git a/full/Changes b/full/Changes
index 809ebc0..9e651d1 100644
--- a/full/Changes
+++ b/full/Changes
@@ -1,5 +1,5 @@
version 0.60.1
-20/03/2018
+28/03/2018
- added admin-related SQL codes (margaretha)
- updated AdminDao (margaretha)
- added optional username query parameter to group list controller (margaretha)
@@ -16,6 +16,9 @@
- added check for hidden groups in VC controller tests (margaretha)
- added search user-group controller (margaretha)
- removed createdBy from VirtualCorpusJson (margaretha)
+ - moved member role setting from the invitation phase to the after-subscription phase (margaretha)
+ - added member role removal after deleting members (margaretha)
+ - added add and delete member role controllers (margaretha)
version 0.60
14/03/2018
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupDao.java
index bee11e3..1d48b02 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupDao.java
@@ -1,7 +1,9 @@
package de.ids_mannheim.korap.dao;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
@@ -65,7 +67,7 @@
group.setCreatedBy(createdBy);
entityManager.persist(group);
- List<Role> roles = new ArrayList<Role>(2);
+ Set<Role> roles = new HashSet<Role>();
roles.add(roleDao
.retrieveRoleById(PredefinedRole.USER_GROUP_ADMIN.getId()));
roles.add(roleDao
@@ -282,23 +284,22 @@
ListJoin<UserGroup, UserGroupMember> members =
root.join(UserGroup_.members);
- restrictions = criteriaBuilder.and(
- criteriaBuilder.equal(members.get(UserGroupMember_.userId),
- userId));
-
- if (status != null){
+ restrictions = criteriaBuilder.and(criteriaBuilder
+ .equal(members.get(UserGroupMember_.userId), userId));
+
+ if (status != null) {
restrictions = criteriaBuilder.and(restrictions, criteriaBuilder
.equal(root.get(UserGroup_.status), status));
}
}
else if (status != null) {
- restrictions = criteriaBuilder
- .equal(root.get(UserGroup_.status), status);
-
+ restrictions =
+ criteriaBuilder.equal(root.get(UserGroup_.status), status);
+
}
query.select(root);
- if (restrictions!=null){
+ if (restrictions != null) {
query.where(restrictions);
}
Query q = entityManager.createQuery(query);
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupMemberDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupMemberDao.java
index b4f2227..47fef03 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupMemberDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupMemberDao.java
@@ -1,5 +1,6 @@
package de.ids_mannheim.korap.dao;
+import java.util.HashSet;
import java.util.List;
import javax.persistence.EntityManager;
@@ -43,16 +44,6 @@
entityManager.persist(member);
}
- // @Deprecated
- // public void addMembers (List<UserGroupMember> members)
- // throws KustvaktException {
- // ParameterChecker.checkObjectValue(members, "List<UserGroupMember>");
- //
- // for (UserGroupMember member : members) {
- // addMember(member);
- // }
- // }
-
public void updateMember (UserGroupMember member) throws KustvaktException {
ParameterChecker.checkObjectValue(member, "UserGroupMember");
entityManager.merge(member);
@@ -70,9 +61,11 @@
if (isSoftDelete) {
member.setStatus(GroupMemberStatus.DELETED);
member.setDeletedBy(deletedBy);
+ member.setRoles(new HashSet<>());
entityManager.persist(member);
}
else {
+ member.setRoles(new HashSet<>());
entityManager.remove(member);
}
}
diff --git a/full/src/main/java/de/ids_mannheim/korap/dto/converter/UserGroupConverter.java b/full/src/main/java/de/ids_mannheim/korap/dto/converter/UserGroupConverter.java
index 0ee2912..3978799 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dto/converter/UserGroupConverter.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dto/converter/UserGroupConverter.java
@@ -2,6 +2,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import org.springframework.stereotype.Component;
@@ -11,6 +12,7 @@
import de.ids_mannheim.korap.entity.Role;
import de.ids_mannheim.korap.entity.UserGroup;
import de.ids_mannheim.korap.entity.UserGroupMember;
+import edu.emory.mathcs.backport.java.util.Collections;
/** Manages conversion of {@link UserGroup} objects to their data access objects (DTO),
* e.g. UserGroupDto. DTO structure defines controllers output, namely the structure of
@@ -24,7 +26,7 @@
public UserGroupDto createUserGroupDto (UserGroup group,
List<UserGroupMember> members, GroupMemberStatus userMemberStatus,
- List<Role> userRoles) {
+ Set<Role> roleSet) {
UserGroupDto dto = new UserGroupDto();
dto.setId(group.getId());
@@ -33,12 +35,8 @@
dto.setOwner(group.getCreatedBy());
dto.setUserMemberStatus(userMemberStatus);
- if (userRoles != null) {
- List<String> roles = new ArrayList<>(userRoles.size());
- for (Role r : userRoles) {
- roles.add(r.getName());
- }
- dto.setUserRoles(roles);
+ if (roleSet != null) {
+ dto.setUserRoles(convertRoleSetToStringList(roleSet));
}
if (members != null) {
@@ -49,12 +47,8 @@
UserGroupMemberDto memberDto = new UserGroupMemberDto();
memberDto.setUserId(member.getUserId());
memberDto.setStatus(member.getStatus());
- List<String> memberRoles =
- new ArrayList<>(member.getRoles().size());
- for (Role r : member.getRoles()) {
- memberRoles.add(r.getName());
- }
- memberDto.setRoles(memberRoles);
+ memberDto.setRoles(
+ convertRoleSetToStringList(member.getRoles()));
memberDtos.add(memberDto);
}
dto.setMembers(memberDtos);
@@ -66,4 +60,12 @@
return dto;
}
+ private List<String> convertRoleSetToStringList (Set<Role> roleSet) {
+ List<String> roles = new ArrayList<>(roleSet.size());
+ for (Role r : roleSet) {
+ roles.add(r.getName());
+ }
+ Collections.sort(roles);
+ return roles;
+ }
}
diff --git a/full/src/main/java/de/ids_mannheim/korap/entity/Role.java b/full/src/main/java/de/ids_mannheim/korap/entity/Role.java
index 2058abf..1474316 100644
--- a/full/src/main/java/de/ids_mannheim/korap/entity/Role.java
+++ b/full/src/main/java/de/ids_mannheim/korap/entity/Role.java
@@ -26,7 +26,7 @@
@Getter
@Entity
@Table(name = "role")
-public class Role {
+public class Role implements Comparable<Role>{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@@ -43,4 +43,15 @@
public String toString () {
return "id=" + id + ", name=" + name;
}
+
+ @Override
+ public int compareTo (Role o) {
+ if (this.getId() > o.getId()){
+ return 1;
+ }
+ else if (this.getId() < o.getId()){
+ return -1;
+ }
+ return 0;
+ }
}
diff --git a/full/src/main/java/de/ids_mannheim/korap/entity/UserGroupMember.java b/full/src/main/java/de/ids_mannheim/korap/entity/UserGroupMember.java
index bcbd100..983535b 100644
--- a/full/src/main/java/de/ids_mannheim/korap/entity/UserGroupMember.java
+++ b/full/src/main/java/de/ids_mannheim/korap/entity/UserGroupMember.java
@@ -1,7 +1,7 @@
package de.ids_mannheim.korap.entity;
import java.time.ZonedDateTime;
-import java.util.List;
+import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
@@ -71,7 +71,7 @@
referencedColumnName = "id"),
uniqueConstraints = @UniqueConstraint(
columnNames = { "group_member_id", "role_id" }))
- private List<Role> roles;
+ private Set<Role> roles;
@Override
public String toString () {
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/MailService.java b/full/src/main/java/de/ids_mannheim/korap/service/MailService.java
index 556d7b7..37b216d 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/MailService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/MailService.java
@@ -18,8 +18,10 @@
import org.springframework.stereotype.Service;
import de.ids_mannheim.korap.config.FullConfiguration;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.ParameterChecker;
/** Manages mail related services, such as sending group member invitations
* per email.
@@ -42,8 +44,12 @@
private FullConfiguration config;
public void sendMemberInvitationNotification (String inviteeName,
- String groupName, String inviter) {
+ String groupName, String inviter) throws KustvaktException {
+ ParameterChecker.checkStringValue(inviteeName, "inviteeName");
+ ParameterChecker.checkStringValue(groupName, "groupName");
+ ParameterChecker.checkStringValue(inviter, "inviter");
+
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare (MimeMessage mimeMessage) throws Exception {
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java b/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java
index e79db77..e8fc312 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java
@@ -3,7 +3,10 @@
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
+import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -56,7 +59,7 @@
@Autowired
private MailService mailService;
- private static List<Role> memberRoles;
+ private static Set<Role> memberRoles;
/** Only users with {@link PredefinedRole#USER_GROUP_ADMIN}
* are allowed to see the members of the group.
@@ -153,16 +156,9 @@
return groupAdmins;
}
- public List<UserGroupMember> retrieveUserGroupAdmins (UserGroup userGroup)
- throws KustvaktException {
- List<UserGroupMember> groupAdmins = groupMemberDao.retrieveMemberByRole(
- userGroup.getId(), PredefinedRole.USER_GROUP_ADMIN.getId());
- return groupAdmins;
- }
-
private void setMemberRoles () {
if (memberRoles == null) {
- memberRoles = new ArrayList<Role>(2);
+ memberRoles = new HashSet<Role>(2);
memberRoles.add(roleDao.retrieveRoleById(
PredefinedRole.USER_GROUP_MEMBER.getId()));
memberRoles.add(roleDao
@@ -199,9 +195,6 @@
UserGroupStatus.ACTIVE);
UserGroup userGroup = userGroupDao.retrieveGroupById(groupId);
- setMemberRoles();
-
-
for (String memberId : groupJson.getMembers()) {
if (memberId.equals(createdBy)) {
// skip owner, already added while creating group.
@@ -266,6 +259,18 @@
String createdBy, GroupMemberStatus status)
throws KustvaktException {
+ addGroupMember(username, userGroup, createdBy, status);
+
+ if (config.isMailEnabled()
+ && userGroup.getStatus() != UserGroupStatus.HIDDEN) {
+ mailService.sendMemberInvitationNotification(username,
+ userGroup.getName(), createdBy);
+ }
+ }
+
+ public void addGroupMember (String username, UserGroup userGroup,
+ String createdBy, GroupMemberStatus status)
+ throws KustvaktException {
int groupId = userGroup.getId();
ParameterChecker.checkIntegerValue(groupId, "userGroupId");
@@ -279,21 +284,12 @@
username, existingStatus.name(), userGroup.getName());
}
- setMemberRoles();
-
UserGroupMember member = new UserGroupMember();
member.setCreatedBy(createdBy);
member.setGroup(userGroup);
- member.setRoles(memberRoles);
member.setStatus(status);
member.setUserId(username);
groupMemberDao.addMember(member);
-
- if (config.isMailEnabled()
- && userGroup.getStatus() != UserGroupStatus.HIDDEN) {
- mailService.sendMemberInvitationNotification(username,
- userGroup.getName(), createdBy);
- }
}
private GroupMemberStatus memberExists (String username, int groupId,
@@ -314,7 +310,7 @@
}
else if (existingStatus.equals(GroupMemberStatus.DELETED)) {
// hard delete, not customizable
- deleteMember(username, groupId, "system", false);
+ doDeleteMember(username, groupId, "system", false);
}
return null;
@@ -348,8 +344,11 @@
private boolean isUserGroupAdmin (String username, UserGroup userGroup)
throws KustvaktException {
+
List<UserGroupMember> userGroupAdmins =
- retrieveUserGroupAdmins(userGroup);
+ groupMemberDao.retrieveMemberByRole(userGroup.getId(),
+ PredefinedRole.USER_GROUP_ADMIN.getId());
+
for (UserGroupMember admin : userGroupAdmins) {
if (username.equals(admin.getUserId())) {
return true;
@@ -359,7 +358,7 @@
}
/** Updates the {@link GroupMemberStatus} of a pending member
- * to {@link GroupMemberStatus#ACTIVE}.
+ * to {@link GroupMemberStatus#ACTIVE} and add default member roles.
*
* @param groupId groupId
* @param username the username of the group member
@@ -403,6 +402,8 @@
if (expiration.isAfter(now)) {
member.setStatus(GroupMemberStatus.ACTIVE);
+ setMemberRoles();
+ member.setRoles(memberRoles);
groupMemberDao.updateMember(member);
}
else {
@@ -442,7 +443,7 @@
|| isUserGroupAdmin(deletedBy, userGroup)
|| adminDao.isAdmin(deletedBy)) {
// soft delete
- deleteMember(memberId, groupId, deletedBy,
+ doDeleteMember(memberId, groupId, deletedBy,
config.isSoftDeleteGroupMember());
}
else {
@@ -461,7 +462,7 @@
* permanently, false otherwise
* @throws KustvaktException
*/
- private void deleteMember (String username, int groupId, String deletedBy,
+ private void doDeleteMember (String username, int groupId, String deletedBy,
boolean isSoftDelete) throws KustvaktException {
UserGroup group = userGroupDao.retrieveGroupById(groupId);
@@ -494,5 +495,75 @@
}
+ public void addMemberRoles (String username, int groupId,
+ String memberUsername, List<Integer> roleIds) throws KustvaktException {
+ ParameterChecker.checkIntegerValue(groupId, "groupId");
+ ParameterChecker.checkStringValue(username, "username");
+ ParameterChecker.checkStringValue(memberUsername, "memberUsername");
+
+ UserGroup userGroup = userGroupDao.retrieveGroupById(groupId, true);
+ UserGroupStatus groupStatus = userGroup.getStatus();
+ if (groupStatus == UserGroupStatus.DELETED){
+ throw new KustvaktException(StatusCodes.GROUP_DELETED,
+ "Usergroup has been deleted.");
+ }
+ else if (isUserGroupAdmin(username, userGroup)
+ || adminDao.isAdmin(username)) {
+
+ UserGroupMember member =
+ groupMemberDao.retrieveMemberById(memberUsername, groupId);
+
+ if (!member.getStatus().equals(GroupMemberStatus.ACTIVE)) {
+ throw new KustvaktException(StatusCodes.GROUP_MEMBER_INACTIVE,
+ memberUsername + " has status " + member.getStatus(),
+ memberUsername, member.getStatus().name());
+ }
+
+ Set<Role> roles = member.getRoles();
+ for (int i = 0; i < roleIds.size(); i++) {
+ roles.add(roleDao.retrieveRoleById(roleIds.get(i)));
+ }
+ member.setRoles(roles);
+ groupMemberDao.updateMember(member);
+
+ }
+ else {
+ throw new KustvaktException(StatusCodes.AUTHORIZATION_FAILED,
+ "Unauthorized operation for user: " + username, username);
+ }
+ }
+
+ public void deleteMemberRoles (String username, int groupId,
+ String memberUsername, List<Integer> roleIds) throws KustvaktException {
+
+ ParameterChecker.checkIntegerValue(groupId, "groupId");
+ ParameterChecker.checkStringValue(username, "username");
+ ParameterChecker.checkStringValue(memberUsername, "memberUsername");
+
+ UserGroup userGroup = userGroupDao.retrieveGroupById(groupId, true);
+
+ if (isUserGroupAdmin(username, userGroup)
+ || adminDao.isAdmin(username)) {
+
+ UserGroupMember member =
+ groupMemberDao.retrieveMemberById(memberUsername, groupId);
+
+ Set<Role> roles = member.getRoles();
+ Iterator<Role> i = roles.iterator();
+ while (i.hasNext()){
+ if (roleIds.contains(i.next().getId())){
+ i.remove();
+ }
+ }
+
+ member.setRoles(roles);
+ groupMemberDao.updateMember(member);
+
+ }
+ else {
+ throw new KustvaktException(StatusCodes.AUTHORIZATION_FAILED,
+ "Unauthorized operation for user: " + username, username);
+ }
+ }
}
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java b/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
index 0643baa..5835d92 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
@@ -423,8 +423,9 @@
UserGroup userGroup =
userGroupService.retrieveHiddenUserGroupByVC(vcId);
try {
- userGroupService.inviteGroupMember(username, userGroup,
+ userGroupService.addGroupMember(username, userGroup,
"system", GroupMemberStatus.ACTIVE);
+ // member roles has not been set (not necessary)
}
catch (KustvaktException e) {
// member exists
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
index 6157b24..ecc00bb 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
@@ -23,7 +23,6 @@
import de.ids_mannheim.korap.constant.UserGroupStatus;
import de.ids_mannheim.korap.dto.UserGroupDto;
-import de.ids_mannheim.korap.dto.VirtualCorpusDto;
import de.ids_mannheim.korap.exceptions.KustvaktException;
import de.ids_mannheim.korap.service.UserGroupService;
import de.ids_mannheim.korap.user.TokenContext;
@@ -81,7 +80,7 @@
}
}
-
+
/** Lists user-groups for system-admin purposes. If username parameter
* is not specified, list user-groups of all users. If status is not
* specified, list user-groups of all statuses.
@@ -110,14 +109,14 @@
}
}
- /** Searches for a specific user-group for system admins.
+ /** Retrieves a specific user-group for system admins.
*
* @param securityContext
* @param groupId group id
* @return a user-group
*/
@GET
- @Path("search/{groupId}")
+ @Path("{groupId}")
public Response searchUserGroup (@Context SecurityContext securityContext,
@PathParam("groupId") int groupId) {
String result;
@@ -133,7 +132,7 @@
}
return Response.ok(result).build();
}
-
+
/** Creates a user group where the user in token context is the
* group owner, and assigns the listed group members with status
* GroupMemberStatus.PENDING.
@@ -169,7 +168,8 @@
}
}
- /** Only group owner and system admins can delete groups.
+ /** Deletes a user-group specified by the group id. Only group owner
+ * and system admins can delete groups.
*
* @param securityContext
* @param groupId
@@ -190,7 +190,7 @@
}
}
- /** Group owner cannot be deleted.
+ /** Deletes a user-group member. Group owner cannot be deleted.
*
* @param securityContext
* @param memberId a username of a group member
@@ -214,6 +214,12 @@
}
}
+ /** Invites group members to join a user-group specified in the JSON object.
+ * @param securityContext
+ * @param group UserGroupJson containing groupId and usernames to be invited
+ * as members
+ * @return if successful, HTTP response status OK
+ */
@POST
@Path("member/invite")
@Consumes(MediaType.APPLICATION_JSON)
@@ -230,6 +236,69 @@
}
}
+ /** Adds roles of an active member of a user-group. Only user-group admins
+ * and system admins are allowed.
+ *
+ * @param securityContext
+ * @param groupId a group id
+ * @param memberUsername the username of a group member
+ * @param roleIds list of role ids
+ * @return if successful, HTTP response status OK
+ */
+ @POST
+ @Path("member/role/add")
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public Response addMemberRoles (@Context SecurityContext securityContext,
+ @FormParam("groupId") int groupId,
+ @FormParam("memberUsername") String memberUsername,
+ @FormParam("roleIds") List<Integer> roleIds) {
+ TokenContext context =
+ (TokenContext) securityContext.getUserPrincipal();
+ try {
+ service.addMemberRoles(context.getUsername(), groupId,
+ memberUsername, roleIds);
+ return Response.ok().build();
+ }
+ catch (KustvaktException e) {
+ throw responseHandler.throwit(e);
+ }
+ }
+
+ /** Deletes roles of a member of a user-group. Only user-group admins
+ * and system admins are allowed.
+ *
+ * @param securityContext
+ * @param groupId a group id
+ * @param memberUsername the username of a group member
+ * @param roleIds list of role ids
+ * @return if successful, HTTP response status OK
+ */
+ @POST
+ @Path("member/role/delete")
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public Response deleteMemberRoles (@Context SecurityContext securityContext,
+ @FormParam("groupId") int groupId,
+ @FormParam("memberUsername") String memberUsername,
+ @FormParam("roleIds") List<Integer> roleIds) {
+ TokenContext context =
+ (TokenContext) securityContext.getUserPrincipal();
+ try {
+ service.deleteMemberRoles(context.getUsername(), groupId,
+ memberUsername, roleIds);
+ return Response.ok().build();
+ }
+ catch (KustvaktException e) {
+ throw responseHandler.throwit(e);
+ }
+ }
+
+ /** Handles requests to accept membership invitation. Only invited users
+ * can subscribe to the corresponding user-group.
+ *
+ * @param securityContext
+ * @param groupId a group id
+ * @return if successful, HTTP response status OK
+ */
@POST
@Path("subscribe")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@@ -246,6 +315,15 @@
}
}
+ /** Handles requests to reject membership invitation. A member can only
+ * unsubscribe him/herself from a group.
+ *
+ * Implemented identical to delete group member.
+ *
+ * @param securityContext
+ * @param groupId
+ * @return if successful, HTTP response status OK
+ */
@POST
@Path("unsubscribe")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
diff --git a/full/src/test/java/de/ids_mannheim/korap/dao/UserGroupDaoTest.java b/full/src/test/java/de/ids_mannheim/korap/dao/UserGroupDaoTest.java
index 4bb8ba0..11f326f 100644
--- a/full/src/test/java/de/ids_mannheim/korap/dao/UserGroupDaoTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/dao/UserGroupDaoTest.java
@@ -2,8 +2,14 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
+import java.util.Set;
+
+import javax.validation.constraints.AssertTrue;
import org.junit.Rule;
import org.junit.Test;
@@ -25,6 +31,7 @@
import de.ids_mannheim.korap.entity.VirtualCorpus;
import de.ids_mannheim.korap.exceptions.KustvaktException;
import de.ids_mannheim.korap.user.User.CorpusAccess;
+import edu.emory.mathcs.backport.java.util.Collections;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:test-config.xml")
@@ -41,7 +48,7 @@
@Rule
public ExpectedException thrown = ExpectedException.none();
-
+
@Test
public void createDeleteNewUserGroup () throws KustvaktException {
@@ -69,15 +76,18 @@
// member roles
List<Role> roles = roleDao.retrieveRoleByGroupMemberId(m.getId());
assertEquals(2, roles.size());
- assertEquals(PredefinedRole.USER_GROUP_ADMIN.getId(), roles.get(0).getId());
- assertEquals(PredefinedRole.VC_ACCESS_ADMIN.getId(), roles.get(1).getId());
+ assertEquals(PredefinedRole.USER_GROUP_ADMIN.getId(),
+ roles.get(0).getId());
+ assertEquals(PredefinedRole.VC_ACCESS_ADMIN.getId(),
+ roles.get(1).getId());
//retrieve VC by group
List<VirtualCorpus> vc = virtualCorpusDao.retrieveVCByGroup(groupId);
assertEquals(0, vc.size());
// soft delete group
- userGroupDao.deleteGroup(groupId, createdBy, config.isSoftDeleteGroup());
+ userGroupDao.deleteGroup(groupId, createdBy,
+ config.isSoftDeleteGroup());
group = userGroupDao.retrieveGroupById(groupId);
assertEquals(UserGroupStatus.DELETED, group.getStatus());
@@ -95,10 +105,16 @@
assertEquals(4, members.size());
UserGroupMember m = members.get(1);
- List<Role> roles = m.getRoles();
+ Set<Role> roles = m.getRoles();
assertEquals(2, roles.size());
- assertEquals(PredefinedRole.USER_GROUP_MEMBER.getId(), roles.get(0).getId());
- assertEquals(PredefinedRole.VC_ACCESS_MEMBER.getId(), roles.get(1).getId());
+
+ List<Role> sortedRoles = new ArrayList<>(roles);
+ Collections.sort(sortedRoles);
+
+ assertEquals(PredefinedRole.USER_GROUP_MEMBER.name(),
+ sortedRoles.get(0).getName());
+ assertEquals(PredefinedRole.VC_ACCESS_MEMBER.name(),
+ sortedRoles.get(1).getName());
}
@Test
@@ -132,8 +148,9 @@
UserGroup group = userGroupDao.retrieveGroupById(groupId);
String createdBy = "dory";
String name = "dory new vc";
- int id = virtualCorpusDao.createVirtualCorpus(name, VirtualCorpusType.PROJECT,
- CorpusAccess.PUB, "corpusSigle=WPD15", "", "", "", createdBy);
+ int id = virtualCorpusDao.createVirtualCorpus(name,
+ VirtualCorpusType.PROJECT, CorpusAccess.PUB,
+ "corpusSigle=WPD15", "", "", "", createdBy);
VirtualCorpus virtualCorpus = virtualCorpusDao.retrieveVCById(id);
userGroupDao.addVCToGroup(virtualCorpus, createdBy,
@@ -148,7 +165,7 @@
vc = virtualCorpusDao.retrieveVCByGroup(groupId);
assertEquals(1, vc.size());
-
+
// delete vc
virtualCorpusDao.deleteVirtualCorpus(virtualCorpus);
}
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerAdminTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerAdminTest.java
index a80397c..d1cbfa6 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerAdminTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerAdminTest.java
@@ -3,6 +3,8 @@
import static org.junit.Assert.assertEquals;
import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -12,6 +14,7 @@
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.ClientResponse.Status;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
import com.sun.jersey.api.client.UniformInterfaceException;
import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
@@ -59,7 +62,7 @@
assertEquals(Status.OK.getStatusCode(), response.getStatus());
String entity = response.getEntity(String.class);
-// System.out.println(entity);
+ // System.out.println(entity);
JsonNode node = JsonUtils.readTree(entity);
assertEquals(3, node.size());
}
@@ -77,12 +80,12 @@
assertEquals(Status.OK.getStatusCode(), response.getStatus());
String entity = response.getEntity(String.class);
-// System.out.println(entity);
+ // System.out.println(entity);
JsonNode node = JsonUtils.readTree(entity);
assertEquals(2, node.size());
}
-
-
+
+
// same as list user-groups of the admin
@Test
public void testListWithoutUsername () throws UniformInterfaceException,
@@ -160,11 +163,114 @@
assertEquals("admin test group", node.get("name").asText());
String groupId = node.get("id").asText();
+ testMemberRole("marlin", groupId);
testInviteMember(groupId);
testDeleteMember(groupId);
testDeleteGroup(groupId);
}
+ private void testMemberRole (String memberUsername, String groupId)
+ throws UniformInterfaceException, ClientHandlerException,
+ KustvaktException {
+
+ // accept invitation
+ MultivaluedMap<String, String> form = new MultivaluedMapImpl();
+ form.add("groupId", groupId);
+
+ ClientResponse response = resource().path("group").path("subscribe")
+ .type(MediaType.APPLICATION_FORM_URLENCODED)
+ .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+ .header(Attributes.AUTHORIZATION,
+ handler.createBasicAuthorizationHeaderValue("marlin",
+ "pass"))
+ .entity(form).post(ClientResponse.class);
+
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+ testAddMemberRoles(groupId, memberUsername);
+ testDeleteMemberRoles(groupId, memberUsername);
+ }
+
+ private void testAddMemberRoles (String groupId, String memberUsername)
+ throws UniformInterfaceException, ClientHandlerException,
+ KustvaktException {
+ MultivaluedMap<String, String> map = new MultivaluedHashMap<>();
+ map.add("groupId", groupId.toString());
+ map.add("memberUsername", memberUsername);
+ map.add("roleIds", "1"); // USER_GROUP_ADMIN
+ map.add("roleIds", "2"); // USER_GROUP_MEMBER
+
+ ClientResponse response =
+ resource().path("group").path("member").path("role").path("add")
+ .type(MediaType.APPLICATION_FORM_URLENCODED)
+ .header(Attributes.AUTHORIZATION,
+ handler.createBasicAuthorizationHeaderValue(
+ adminUsername, "password"))
+ .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+ .entity(map).post(ClientResponse.class);
+
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+ JsonNode node = retrieveGroup(groupId).at("/members");
+ JsonNode member;
+ for (int i = 0; i < node.size(); i++) {
+ member = node.get(i);
+ if (member.at("/userId").asText().equals(memberUsername)) {
+ assertEquals(3, member.at("/roles").size());
+ assertEquals(PredefinedRole.USER_GROUP_ADMIN.name(),
+ member.at("/roles/0").asText());
+ break;
+ }
+ }
+ }
+
+ private void testDeleteMemberRoles (String groupId, String memberUsername)
+ throws UniformInterfaceException, ClientHandlerException,
+ KustvaktException {
+ MultivaluedMap<String, String> map = new MultivaluedHashMap<>();
+ map.add("groupId", groupId.toString());
+ map.add("memberUsername", memberUsername);
+ map.add("roleIds", "1"); // USER_GROUP_ADMIN
+
+ ClientResponse response = resource().path("group").path("member")
+ .path("role").path("delete")
+ .type(MediaType.APPLICATION_FORM_URLENCODED)
+ .header(Attributes.AUTHORIZATION,
+ handler.createBasicAuthorizationHeaderValue(
+ adminUsername, "password"))
+ .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32").entity(map)
+ .post(ClientResponse.class);
+
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+ JsonNode node = retrieveGroup(groupId).at("/members");
+ JsonNode member;
+ for (int i = 0; i < node.size(); i++) {
+ member = node.get(i);
+ if (member.at("/userId").asText().equals(memberUsername)) {
+ assertEquals(2, member.at("/roles").size());
+ break;
+ }
+ }
+ }
+
+ private JsonNode retrieveGroup (String groupId)
+ throws UniformInterfaceException, ClientHandlerException,
+ KustvaktException {
+ ClientResponse response = resource().path("group").path(groupId)
+ .header(Attributes.AUTHORIZATION,
+ handler.createBasicAuthorizationHeaderValue(
+ adminUsername, "pass"))
+ .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+ .get(ClientResponse.class);
+
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+ String entity = response.getEntity(String.class);
+ JsonNode node = JsonUtils.readTree(entity);
+ return node;
+ }
+
private void testDeleteGroup (String groupId)
throws UniformInterfaceException, ClientHandlerException,
KustvaktException {
@@ -233,10 +339,7 @@
assertEquals("darla", node.at("/members/3/userId").asText());
assertEquals(GroupMemberStatus.PENDING.name(),
node.at("/members/3/status").asText());
- assertEquals(PredefinedRole.USER_GROUP_MEMBER.name(),
- node.at("/members/3/roles/0").asText());
- assertEquals(PredefinedRole.VC_ACCESS_MEMBER.name(),
- node.at("/members/3/roles/1").asText());
+ assertEquals(0, node.at("/members/3/roles").size());
}
}
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java
index 89d7ecd..373d194 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java
@@ -151,7 +151,7 @@
.get(ClientResponse.class);
String entity = response.getEntity(String.class);
- // System.out.println(entity);
+// System.out.println(entity);
JsonNode node = JsonUtils.readTree(entity);
assertEquals(1, node.size());
node = node.get(0);
@@ -171,11 +171,7 @@
assertEquals("marlin", node.at("/members/1/userId").asText());
assertEquals(GroupMemberStatus.PENDING.name(),
node.at("/members/1/status").asText());
- assertEquals(PredefinedRole.USER_GROUP_MEMBER.name(),
- node.at("/members/1/roles/0").asText());
- assertEquals(PredefinedRole.VC_ACCESS_MEMBER.name(),
- node.at("/members/1/roles/1").asText());
-
+ assertEquals(0, node.at("/members/1/roles").size());
testInviteMember(groupId);
@@ -212,10 +208,6 @@
JsonNode node = JsonUtils.readTree(entity);
node = node.get(0);
assertEquals(3, node.get("members").size());
- assertEquals("nemo", node.at("/members/1/userId").asText());
- assertEquals(GroupMemberStatus.PENDING.name(),
- node.at("/members/1/status").asText());
-
}
private void testDeleteMemberUnauthorized (String groupId)
@@ -316,9 +308,9 @@
assertEquals(groupId, node.at("/0/id").asText());
// check group members
- for (int i=0; i< node.at("/0/members").size(); i++){
+ for (int i = 0; i < node.at("/0/members").size(); i++) {
assertEquals(GroupMemberStatus.DELETED.name(),
- node.at("/0/members/"+i+"/status").asText());
+ node.at("/0/members/" + i + "/status").asText());
}
}
@@ -424,10 +416,7 @@
assertEquals("darla", node.at("/members/3/userId").asText());
assertEquals(GroupMemberStatus.PENDING.name(),
node.at("/members/3/status").asText());
- assertEquals(PredefinedRole.USER_GROUP_MEMBER.name(),
- node.at("/members/3/roles/0").asText());
- assertEquals(PredefinedRole.VC_ACCESS_MEMBER.name(),
- node.at("/members/3/roles/1").asText());
+ assertEquals(0, node.at("/members/3/roles").size());
}
private void testInviteDeletedMember () throws UniformInterfaceException,
@@ -602,7 +591,7 @@
// retrieve marlin group
JsonNode node = retrieveUserGroups("marlin");
- // System.out.println(node);
+ // System.out.println(node);
assertEquals(2, node.size());
JsonNode group = node.get(1);
@@ -613,9 +602,15 @@
assertEquals(0, group.at("/members").size());
assertEquals(GroupMemberStatus.ACTIVE.name(),
group.at("/userMemberStatus").asText());
+ assertEquals(PredefinedRole.USER_GROUP_MEMBER.name(),
+ group.at("/userRoles/0").asText());
+ assertEquals(PredefinedRole.VC_ACCESS_MEMBER.name(),
+ group.at("/userRoles/1").asText());
+
// unsubscribe marlin from dory group
testUnsubscribeActiveMember(form);
+ checkGroupMemberRole("2", "marlin");
// invite marlin to dory group to set back the GroupMemberStatus.PENDING
testInviteDeletedMember();
@@ -748,6 +743,29 @@
assertEquals(1, node.size());
}
+ private void checkGroupMemberRole (String groupId, String deletedMemberName)
+ throws KustvaktException {
+ ClientResponse response = resource().path("group").path(groupId)
+ .header(Attributes.AUTHORIZATION,
+ handler.createBasicAuthorizationHeaderValue(admin,
+ "pass"))
+ .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+ .get(ClientResponse.class);
+ String entity = response.getEntity(String.class);
+
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+ JsonNode node = JsonUtils.readTree(entity).at("/members");
+ JsonNode member;
+ for (int i = 0; i < node.size(); i++) {
+ member = node.get(i);
+ if (deletedMemberName.equals(member.at("/userId").asText())) {
+ assertEquals(0, node.at("/roles").size());
+ break;
+ }
+ }
+ }
+
@Test
public void testUnsubscribeDeletedMember ()
throws UniformInterfaceException, ClientHandlerException,
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
index b61c972..7ef7361 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
@@ -362,7 +362,8 @@
//EM: check if the hidden groups are deleted as well
node = testCheckHiddenGroup(groupId);
- assertEquals(605, node.at("/errors/0/0").asInt());
+ assertEquals(StatusCodes.GROUP_NOT_FOUND,
+ node.at("/errors/0/0").asInt());
assertEquals("Group with id 5 is not found",
node.at("/errors/0/1").asText());
}
@@ -370,13 +371,12 @@
private JsonNode testCheckHiddenGroup (String groupId)
throws UniformInterfaceException, ClientHandlerException,
KustvaktException {
- ClientResponse response =
- resource().path("group").path("search").path(groupId)
- .header(Attributes.AUTHORIZATION,
- handler.createBasicAuthorizationHeaderValue(
- "admin", "pass"))
- .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
- .get(ClientResponse.class);
+ ClientResponse response = resource().path("group").path(groupId)
+ .header(Attributes.AUTHORIZATION,
+ handler.createBasicAuthorizationHeaderValue("admin",
+ "pass"))
+ .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+ .get(ClientResponse.class);
String entity = response.getEntity(String.class);
return JsonUtils.readTree(entity);