From 0479a62156453a268e80a7c975d3831692945afc Mon Sep 17 00:00:00 2001 From: Sonia Zorba <sonia.zorba@inaf.it> Date: Mon, 12 Aug 2019 22:52:09 +0200 Subject: [PATCH] Added web service controller logic and tests --- .../ia2/gms/controller/GroupsController.java | 8 +- .../gms/controller/WebServiceController.java | 72 +++++- .../inaf/ia2/gms/model/AddMemberRequest.java | 27 +++ .../ia2/gms/model/AddPermissionWsRequest.java | 39 ++++ .../ia2/gms/model/CreateGroupRequest.java | 4 + .../ia2/gms/model/PrepareToJoinRequest.java | 23 ++ .../inaf/ia2/gms/persistence/GroupsDAO.java | 42 +++- .../ia2/gms/persistence/MembershipsDAO.java | 68 +++++- .../ia2/gms/persistence/PermissionsDAO.java | 36 +++ .../persistence/model/MembershipEntity.java | 4 + .../persistence/model/PermissionEntity.java | 7 +- .../inaf/ia2/gms/service/GroupsService.java | 44 +++- .../inaf/ia2/gms/service/MembersService.java | 17 ++ .../ia2/gms/service/PermissionsService.java | 24 +- .../controller/WebServiceControllerTest.java | 215 ++++++++++++++++++ .../PermissionsServiceIntegrationTest.java | 2 +- 16 files changed, 601 insertions(+), 31 deletions(-) create mode 100644 gms/src/main/java/it/inaf/ia2/gms/model/AddMemberRequest.java create mode 100644 gms/src/main/java/it/inaf/ia2/gms/model/AddPermissionWsRequest.java create mode 100644 gms/src/main/java/it/inaf/ia2/gms/model/PrepareToJoinRequest.java create mode 100644 gms/src/test/java/it/inaf/ia2/gms/controller/WebServiceControllerTest.java diff --git a/gms/src/main/java/it/inaf/ia2/gms/controller/GroupsController.java b/gms/src/main/java/it/inaf/ia2/gms/controller/GroupsController.java index 11b05b0..4b91c0e 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/controller/GroupsController.java +++ b/gms/src/main/java/it/inaf/ia2/gms/controller/GroupsController.java @@ -82,7 +82,13 @@ public class GroupsController { @DeleteMapping(value = "/group/{groupId}", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public ResponseEntity<?> deleteGroup(@PathVariable("groupId") String groupId, PaginatedModelRequest request) { - GroupEntity parent = groupsService.deleteGroup(groupId, session.getUserId()); + GroupEntity group = groupsService.getGroupById(groupId); + + if (permissionsService.getGroupPermission(group, session.getUserId()) != Permission.ADMIN) { + throw new UnauthorizedException("Missing admin privileges"); + } + + GroupEntity parent = groupsService.deleteGroup(group); PaginatedData<GroupNode> groupsPanel = getGroupsPanel(parent.getId(), request); diff --git a/gms/src/main/java/it/inaf/ia2/gms/controller/WebServiceController.java b/gms/src/main/java/it/inaf/ia2/gms/controller/WebServiceController.java index a6ff8c8..f71e4e3 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/controller/WebServiceController.java +++ b/gms/src/main/java/it/inaf/ia2/gms/controller/WebServiceController.java @@ -1,15 +1,28 @@ package it.inaf.ia2.gms.controller; +import it.inaf.ia2.gms.exception.BadRequestException; +import it.inaf.ia2.gms.model.AddPermissionWsRequest; +import it.inaf.ia2.gms.model.Permission; +import it.inaf.ia2.gms.model.PrepareToJoinRequest; import it.inaf.ia2.gms.persistence.model.GroupEntity; +import it.inaf.ia2.gms.persistence.model.MembershipEntity; +import it.inaf.ia2.gms.persistence.model.PermissionEntity; import it.inaf.ia2.gms.service.GroupsService; +import it.inaf.ia2.gms.service.MembersService; +import it.inaf.ia2.gms.service.PermissionsService; +import java.util.Arrays; import java.util.List; import java.util.Optional; +import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @@ -19,11 +32,17 @@ public class WebServiceController { @Autowired private GroupsService groupsService; + @Autowired + private MembersService membersService; + + @Autowired + private PermissionsService permissionsService; + /** * Creates a group and its ancestors if they are missing. It doesn't fail if * the last group already exists. */ - @PostMapping("/group") + @PostMapping(value = "/group", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public ResponseEntity<GroupEntity> createGroup(@RequestBody List<String> names) { GroupEntity group = groupsService.getRoot(); @@ -40,27 +59,64 @@ public class WebServiceController { return new ResponseEntity<>(group, HttpStatus.CREATED); } - public void deleteGroup() { + @DeleteMapping("/group") + public ResponseEntity<?> deleteGroupByPath(@RequestParam("names") String[] names) { - } + GroupEntity groupToDelete = getGroupByNames(Arrays.asList(names)); + + groupsService.deleteGroup(groupToDelete); - public void addMember() { + return ResponseEntity.noContent().build(); + } + @PostMapping(value = "/member", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public ResponseEntity<MembershipEntity> addMember(@RequestBody MembershipEntity request) { + MembershipEntity membership = membersService.addMember(request.getGroupId(), request.getUserId()); + return new ResponseEntity<>(membership, HttpStatus.CREATED); } - public void removeMember() { + @DeleteMapping("/member") + public ResponseEntity<?> removeMember(@RequestParam("names") String[] names, @RequestParam("userId") String userId) { + + GroupEntity group = getGroupByNames(Arrays.asList(names)); + membersService.removeMember(group.getId(), userId); + + return ResponseEntity.noContent().build(); } - public void addPrivilege() { + @PostMapping(value = "/permission", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public ResponseEntity<PermissionEntity> addPermission(@Valid @RequestBody AddPermissionWsRequest request) { + + GroupEntity group = getGroupByNames(request.getNames()); + PermissionEntity newPermission = permissionsService.addPermission(group, request.getUserId(), request.getPermission()); + + return new ResponseEntity<>(newPermission, HttpStatus.CREATED); } - public void deletePrivilege() { + @DeleteMapping("/permission") + public ResponseEntity<?> deletePermission(@RequestParam("names") String[] names, + @RequestParam("userId") String userId, @RequestParam("permission") Permission permission) { + + GroupEntity group = getGroupByNames(Arrays.asList(names)); + permissionsService.deletePermission(group, userId, permission); + + return ResponseEntity.noContent().build(); } - public void prepareToJoin() { + @PostMapping(value = "/prepare-join", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public ResponseEntity<?> prepareToJoin(@Valid @RequestBody PrepareToJoinRequest request) { + + permissionsService.movePermissions(request.getFromUserId(), request.getToUserId()); + membersService.moveMemberships(request.getFromUserId(), request.getToUserId()); + + return ResponseEntity.ok().build(); + } + private GroupEntity getGroupByNames(List<String> names) { + return groupsService.findGroupByNames(names) + .orElseThrow(() -> new BadRequestException("Unable to find requested group")); } } diff --git a/gms/src/main/java/it/inaf/ia2/gms/model/AddMemberRequest.java b/gms/src/main/java/it/inaf/ia2/gms/model/AddMemberRequest.java new file mode 100644 index 0000000..a22dc85 --- /dev/null +++ b/gms/src/main/java/it/inaf/ia2/gms/model/AddMemberRequest.java @@ -0,0 +1,27 @@ +package it.inaf.ia2.gms.model; + +import javax.validation.constraints.NotEmpty; + +public class AddMemberRequest extends PaginatedModelRequest { + + @NotEmpty + private String groupId; + @NotEmpty + private String userId; + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } +} diff --git a/gms/src/main/java/it/inaf/ia2/gms/model/AddPermissionWsRequest.java b/gms/src/main/java/it/inaf/ia2/gms/model/AddPermissionWsRequest.java new file mode 100644 index 0000000..6e45d07 --- /dev/null +++ b/gms/src/main/java/it/inaf/ia2/gms/model/AddPermissionWsRequest.java @@ -0,0 +1,39 @@ +package it.inaf.ia2.gms.model; + +import java.util.List; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +public class AddPermissionWsRequest { + + @NotNull + private List<String> names; + @NotEmpty + private String userId; + @NotNull + private Permission permission; + + public List<String> getNames() { + return names; + } + + public void setNames(List<String> names) { + this.names = names; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public Permission getPermission() { + return permission; + } + + public void setPermission(Permission permission) { + this.permission = permission; + } +} diff --git a/gms/src/main/java/it/inaf/ia2/gms/model/CreateGroupRequest.java b/gms/src/main/java/it/inaf/ia2/gms/model/CreateGroupRequest.java index c7444a9..d13ab80 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/model/CreateGroupRequest.java +++ b/gms/src/main/java/it/inaf/ia2/gms/model/CreateGroupRequest.java @@ -1,8 +1,12 @@ package it.inaf.ia2.gms.model; +import javax.validation.constraints.NotEmpty; + public class CreateGroupRequest extends PaginatedModelRequest { + @NotEmpty private String parentGroupId; + @NotEmpty private String newGroupName; public String getNewGroupName() { diff --git a/gms/src/main/java/it/inaf/ia2/gms/model/PrepareToJoinRequest.java b/gms/src/main/java/it/inaf/ia2/gms/model/PrepareToJoinRequest.java new file mode 100644 index 0000000..84681f7 --- /dev/null +++ b/gms/src/main/java/it/inaf/ia2/gms/model/PrepareToJoinRequest.java @@ -0,0 +1,23 @@ +package it.inaf.ia2.gms.model; + +public class PrepareToJoinRequest { + + private String fromUserId; + private String toUserId; + + public String getFromUserId() { + return fromUserId; + } + + public void setFromUserId(String fromUserId) { + this.fromUserId = fromUserId; + } + + public String getToUserId() { + return toUserId; + } + + public void setToUserId(String toUserId) { + this.toUserId = toUserId; + } +} diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/GroupsDAO.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/GroupsDAO.java index 9f84eae..80d0c87 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/GroupsDAO.java +++ b/gms/src/main/java/it/inaf/ia2/gms/persistence/GroupsDAO.java @@ -3,6 +3,8 @@ package it.inaf.ia2.gms.persistence; import it.inaf.ia2.gms.model.GroupBreadcrumb; import it.inaf.ia2.gms.persistence.model.GroupEntity; import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import java.sql.Types; import java.util.ArrayList; import java.util.HashMap; @@ -131,15 +133,7 @@ public class GroupsDAO { ps.setObject(1, getSubGroupsPath(path), Types.OTHER); return ps; }, resultSet -> { - List<GroupEntity> groups = new ArrayList<>(); - while (resultSet.next()) { - GroupEntity group = new GroupEntity(); - group.setId(resultSet.getString("id")); - group.setName(resultSet.getString("name")); - group.setPath(resultSet.getString("path")); - groups.add(group); - } - return groups; + return getGroupsFromResultSet(resultSet); }); } @@ -151,6 +145,36 @@ public class GroupsDAO { return path; } + public List<GroupEntity> findGroupsByNames(List<String> names) { + + String sql = "SELECT id, name, path from gms_group WHERE name IN (" + + String.join(",", names.stream().map(g -> "?").collect(Collectors.toList())) + + ")"; + + return jdbcTemplate.query(conn -> { + PreparedStatement ps = conn.prepareStatement(sql); + int i = 0; + for (String name : names) { + ps.setString(++i, name); + } + return ps; + }, resultSet -> { + return getGroupsFromResultSet(resultSet); + }); + } + + private List<GroupEntity> getGroupsFromResultSet(ResultSet resultSet) throws SQLException { + List<GroupEntity> groups = new ArrayList<>(); + while (resultSet.next()) { + GroupEntity group = new GroupEntity(); + group.setId(resultSet.getString("id")); + group.setName(resultSet.getString("name")); + group.setPath(resultSet.getString("path")); + groups.add(group); + } + return groups; + } + public Map<String, Boolean> getHasChildrenMap(Set<String> groupIds) { if (groupIds.isEmpty()) { diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/MembershipsDAO.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/MembershipsDAO.java index d6b832d..a18832c 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/MembershipsDAO.java +++ b/gms/src/main/java/it/inaf/ia2/gms/persistence/MembershipsDAO.java @@ -1,13 +1,79 @@ package it.inaf.ia2.gms.persistence; import it.inaf.ia2.gms.persistence.model.MembershipEntity; +import java.sql.PreparedStatement; +import java.util.ArrayList; import java.util.List; +import javax.sql.DataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; @Component public class MembershipsDAO { + private final JdbcTemplate jdbcTemplate; + + @Autowired + public MembershipsDAO(DataSource dataSource) { + jdbcTemplate = new JdbcTemplate(dataSource); + } + public List<MembershipEntity> findByGroup(String groupId) { - throw new UnsupportedOperationException("TODO"); + + String sql = "SELECT user_id FROM gms_membership WHERE group_id = ?"; + + return jdbcTemplate.query(conn -> { + PreparedStatement ps = conn.prepareStatement(sql); + ps.setString(1, groupId); + return ps; + }, resultSet -> { + List<MembershipEntity> members = new ArrayList<>(); + while (resultSet.next()) { + MembershipEntity membership = new MembershipEntity(); + membership.setGroupId(groupId); + membership.setUserId(resultSet.getString("user_id")); + members.add(membership); + } + return members; + }); + } + + public MembershipEntity addMember(MembershipEntity membership) { + + String sql = "INSERT INTO gms_membership (group_id, user_id) VALUES (?, ?)"; + + jdbcTemplate.update(conn -> { + PreparedStatement ps = conn.prepareStatement(sql); + ps.setString(1, membership.getGroupId()); + ps.setString(2, membership.getUserId()); + return ps; + }); + + return membership; + } + + public void removeMembership(String groupId, String userId) { + + String sql = "DELETE FROM gms_membership WHERE group_id = ? AND user_id = ?"; + + jdbcTemplate.update(conn -> { + PreparedStatement ps = conn.prepareStatement(sql); + ps.setString(1, groupId); + ps.setString(2, userId); + return ps; + }); + } + + public void moveMemberships(String fromUserId, String toUserId) { + + String sql = "UPDATE gms_membership SET user_id = ? WHERE user_id = ?"; + + jdbcTemplate.update(conn -> { + PreparedStatement ps = conn.prepareStatement(sql); + ps.setString(1, toUserId); + ps.setString(2, fromUserId); + return ps; + }); } } diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/PermissionsDAO.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/PermissionsDAO.java index 4162110..e442b65 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/PermissionsDAO.java +++ b/gms/src/main/java/it/inaf/ia2/gms/persistence/PermissionsDAO.java @@ -6,6 +6,7 @@ import java.sql.PreparedStatement; import java.sql.Types; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; @@ -84,6 +85,29 @@ public class PermissionsDAO { }); } + public Optional<PermissionEntity> findPermissionEntity(String groupId, String userId, Permission permission) { + + String sql = "SELECT group_path FROM gms_permission WHERE group_id = ? AND user_id = ? AND permission = ?"; + + return jdbcTemplate.query(conn -> { + PreparedStatement ps = conn.prepareStatement(sql); + ps.setString(1, groupId); + ps.setString(2, userId); + ps.setObject(3, permission.toString(), Types.OTHER); + return ps; + }, resultSet -> { + if (resultSet.next()) { + PermissionEntity permissionEntity = new PermissionEntity(); + permissionEntity.setGroupId(groupId); + permissionEntity.setUserId(userId); + permissionEntity.setPermission(permission); + permissionEntity.setGroupPath(resultSet.getString("group_path")); + return Optional.of(permissionEntity); + } + return Optional.empty(); + }); + } + public List<PermissionEntity> getGroupsPermissions(String groupId) { String sql = "SELECT user_id, permission, group_path FROM gms_permission WHERE group_id = ?"; @@ -118,4 +142,16 @@ public class PermissionsDAO { return ps; }); } + + public void movePermissions(String fromUserId, String toUserId) { + + String sql = "UPDATE gms_permission SET user_id = ? WHERE user_id = ?"; + + jdbcTemplate.update(conn -> { + PreparedStatement ps = conn.prepareStatement(sql); + ps.setString(1, toUserId); + ps.setString(2, fromUserId); + return ps; + }); + } } diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/MembershipEntity.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/MembershipEntity.java index 9625a87..81c793c 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/MembershipEntity.java +++ b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/MembershipEntity.java @@ -1,8 +1,12 @@ package it.inaf.ia2.gms.persistence.model; +import javax.validation.constraints.NotEmpty; + public class MembershipEntity { + @NotEmpty private String groupId; + @NotEmpty private String userId; public String getGroupId() { diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/PermissionEntity.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/PermissionEntity.java index 957e658..98bfc6f 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/PermissionEntity.java +++ b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/PermissionEntity.java @@ -1,13 +1,18 @@ package it.inaf.ia2.gms.persistence.model; import it.inaf.ia2.gms.model.Permission; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; public class PermissionEntity { + @NotEmpty private String userId; + @NotEmpty private String groupId; + @NotNull private Permission permission; - + // The group path is copied here for performance reasons private String groupPath; diff --git a/gms/src/main/java/it/inaf/ia2/gms/service/GroupsService.java b/gms/src/main/java/it/inaf/ia2/gms/service/GroupsService.java index 12aa216..1647616 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/service/GroupsService.java +++ b/gms/src/main/java/it/inaf/ia2/gms/service/GroupsService.java @@ -81,13 +81,7 @@ public class GroupsService { return groupsDAO.updateGroup(group); } - public GroupEntity deleteGroup(String groupId, String userId) { - - GroupEntity group = getGroupById(groupId); - - if (permissionsService.getGroupPermission(group, userId) != Permission.ADMIN) { - throw new UnauthorizedException("Missing admin privileges"); - } + public GroupEntity deleteGroup(GroupEntity group) { if (ROOT.equals(group.getId())) { throw new UnauthorizedException("It is not possible to remove the ROOT"); @@ -97,7 +91,7 @@ public class GroupsService { GroupEntity parent = groupsDAO.findGroupByPath(parentPath) .orElseThrow(() -> new BadRequestException("No group found at path " + parentPath)); - groupsDAO.deleteGroupById(groupId); + groupsDAO.deleteGroupById(group.getId()); return parent; } @@ -123,4 +117,38 @@ public class GroupsService { public Optional<GroupEntity> findGroupByParentAndName(GroupEntity parent, String childName) { return groupsDAO.findGroupByParentAndName(parent.getPath(), childName); } + + /** + * Retrieves a group given the sequence of group names corresponding to its + * path. + */ + public Optional<GroupEntity> findGroupByNames(List<String> names) { + + // There can be groups with the same name under different parents, so + // after retrieving this list it is necessary to match for the correct + // group + List<GroupEntity> groups = groupsDAO.findGroupsByNames(names); + + String parentPath = ""; + GroupEntity group = null; + for (String name : names) { + group = findGroup(groups, parentPath, name); + if (group == null) { + break; + } else { + parentPath = group.getPath(); + } + } + + return Optional.ofNullable(group); + } + + private GroupEntity findGroup(List<GroupEntity> groups, String parentPath, String groupName) { + for (GroupEntity group : groups) { + if (parentPath.equals(group.getParentPath()) && groupName.equals(group.getName())) { + return group; + } + } + return null; + } } diff --git a/gms/src/main/java/it/inaf/ia2/gms/service/MembersService.java b/gms/src/main/java/it/inaf/ia2/gms/service/MembersService.java index 7f9ab1d..b05fb52 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/service/MembersService.java +++ b/gms/src/main/java/it/inaf/ia2/gms/service/MembersService.java @@ -29,4 +29,21 @@ public class MembersService { return rapClient.getUsers(userIdentifiers); } + + public MembershipEntity addMember(String groupId, String userId) { + + MembershipEntity membership = new MembershipEntity(); + membership.setGroupId(groupId); + membership.setUserId(userId); + + return membershipsDAO.addMember(membership); + } + + public void removeMember(String groupId, String userId) { + membershipsDAO.removeMembership(groupId, userId); + } + + public void moveMemberships(String fromUserId, String toUserId) { + membershipsDAO.moveMemberships(fromUserId, toUserId); + } } diff --git a/gms/src/main/java/it/inaf/ia2/gms/service/PermissionsService.java b/gms/src/main/java/it/inaf/ia2/gms/service/PermissionsService.java index ad1f5a9..96170b1 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/service/PermissionsService.java +++ b/gms/src/main/java/it/inaf/ia2/gms/service/PermissionsService.java @@ -10,6 +10,7 @@ import it.inaf.ia2.gms.rap.RapClient; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; @@ -59,7 +60,26 @@ public class PermissionsService { return PermissionUtils.getGroupPermission(group, permissions).orElse(null); } - public void deletePermission(String userId, String groupId, Permission permission) { - permissionsDAO.deletePermission(userId, groupId, permission); + public void deletePermission(GroupEntity group, String userId, Permission permission) { + permissionsDAO.deletePermission(group.getId(), userId, permission); + } + + public PermissionEntity addPermission(GroupEntity group, String userId, Permission permission) { + + PermissionEntity permissionEntity = new PermissionEntity(); + permissionEntity.setGroupId(group.getId()); + permissionEntity.setUserId(userId); + permissionEntity.setPermission(permission); + permissionEntity.setGroupPath(group.getPath()); + + return permissionsDAO.createPermission(permissionEntity); + } + + public Optional<PermissionEntity> findPermissionEntity(String groupId, String userId, Permission permission) { + return permissionsDAO.findPermissionEntity(groupId, userId, permission); + } + + public void movePermissions(String fromUserId, String toUserId) { + permissionsDAO.movePermissions(fromUserId, toUserId); } } diff --git a/gms/src/test/java/it/inaf/ia2/gms/controller/WebServiceControllerTest.java b/gms/src/test/java/it/inaf/ia2/gms/controller/WebServiceControllerTest.java new file mode 100644 index 0000000..fe53d1f --- /dev/null +++ b/gms/src/test/java/it/inaf/ia2/gms/controller/WebServiceControllerTest.java @@ -0,0 +1,215 @@ +package it.inaf.ia2.gms.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import it.inaf.ia2.gms.model.AddPermissionWsRequest; +import it.inaf.ia2.gms.model.Permission; +import it.inaf.ia2.gms.model.PrepareToJoinRequest; +import it.inaf.ia2.gms.persistence.model.GroupEntity; +import it.inaf.ia2.gms.persistence.model.MembershipEntity; +import it.inaf.ia2.gms.persistence.model.PermissionEntity; +import it.inaf.ia2.gms.service.GroupsService; +import it.inaf.ia2.gms.service.MembersService; +import it.inaf.ia2.gms.service.PermissionsService; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static org.hamcrest.CoreMatchers.is; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import static org.mockito.ArgumentMatchers.eq; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +@RunWith(MockitoJUnitRunner.class) +public class WebServiceControllerTest { + + @Mock + private GroupsService groupsService; + + @Mock + private MembersService membersService; + + @Mock + private PermissionsService permissionsService; + + @InjectMocks + private WebServiceController controller; + + @Autowired + private MockMvc mockMvc; + + private final ObjectMapper mapper = new ObjectMapper(); + + @Before + public void init() { + mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); + } + + @Test + public void testCreateGroup() throws Exception { + + GroupEntity root = new GroupEntity(); + root.setId(GroupsService.ROOT); + root.setName(GroupsService.ROOT); + root.setPath(""); + + GroupEntity lbt = new GroupEntity(); + lbt.setId("lbt_id"); + lbt.setName("LBT"); + lbt.setPath("lbt_id"); + + GroupEntity inaf = getInafGroup(); + + when(groupsService.getRoot()).thenReturn(root); + when(groupsService.findGroupByParentAndName(eq(root), eq("LBT"))).thenReturn(Optional.of(lbt)); + when(groupsService.addGroup(eq(lbt), eq("INAF"))).thenReturn(inaf); + + List<String> names = getNames("LBT", "INAF"); + + mockMvc.perform(post("/ws/group") + .content(mapper.writeValueAsString(names)) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id", is("inaf_id"))) + .andExpect(jsonPath("$.name", is("INAF"))) + .andExpect(jsonPath("$.path", is("lbt_id.inaf_id"))) + .andExpect(jsonPath("$.parentPath", is("lbt_id"))); + } + + @Test + public void testDeleteGroupByPath() throws Exception { + + List<String> names = getNames("LBT", "INAF"); + + GroupEntity inaf = getInafGroup(); + + when(groupsService.findGroupByNames(names)).thenReturn(Optional.of(inaf)); + + mockMvc.perform(delete("/ws/group?names=LBT&names=INAF")) + .andExpect(status().isNoContent()); + + verify(groupsService, times(1)).deleteGroup(eq(inaf)); + } + + @Test + public void testAddMember() throws Exception { + + MembershipEntity membership = new MembershipEntity(); + membership.setGroupId("group_id"); + membership.setUserId("user_id"); + + when(membersService.addMember(eq("group_id"), eq("user_id"))) + .thenReturn(membership); + + mockMvc.perform(post("/ws/member") + .content(mapper.writeValueAsString(membership)) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.groupId", is("group_id"))) + .andExpect(jsonPath("$.userId", is("user_id"))); + } + + @Test + public void testRemoveMember() throws Exception { + + List<String> names = getNames("LBT", "INAF"); + + GroupEntity inaf = getInafGroup(); + + when(groupsService.findGroupByNames(names)).thenReturn(Optional.of(inaf)); + + mockMvc.perform(delete("/ws/member?names=LBT&names=INAF&userId=user_id")) + .andExpect(status().isNoContent()); + + verify(membersService, times(1)).removeMember(eq(inaf.getId()), eq("user_id")); + } + + @Test + public void testAddPermission() throws Exception { + + List<String> names = getNames("LBT", "INAF"); + + AddPermissionWsRequest request = new AddPermissionWsRequest(); + request.setNames(names); + request.setUserId("user_id"); + request.setPermission(Permission.ADMIN); + + GroupEntity inaf = getInafGroup(); + when(groupsService.findGroupByNames(names)).thenReturn(Optional.of(inaf)); + + PermissionEntity permissionEntity = new PermissionEntity(); + permissionEntity.setGroupId(inaf.getId()); + permissionEntity.setUserId(request.getUserId()); + permissionEntity.setPermission(request.getPermission()); + permissionEntity.setGroupPath(inaf.getPath()); + + when(permissionsService.addPermission(eq(inaf), eq(request.getUserId()), + eq(request.getPermission()))).thenReturn(permissionEntity); + + mockMvc.perform(post("/ws/permission") + .content(mapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.groupId", is(inaf.getId()))) + .andExpect(jsonPath("$.userId", is(request.getUserId()))) + .andExpect(jsonPath("$.permission", is("ADMIN"))); + + verify(permissionsService, times(1)) + .addPermission(eq(inaf), eq(request.getUserId()), eq(request.getPermission())); + } + + @Test + public void testDeletePermission() throws Exception { + + List<String> names = getNames("LBT", "INAF"); + GroupEntity inaf = getInafGroup(); + when(groupsService.findGroupByNames(names)).thenReturn(Optional.of(inaf)); + + mockMvc.perform(delete("/ws/permission?names=LBT&names=INAF&userId=user_id&permission=ADMIN")) + .andExpect(status().isNoContent()); + + verify(permissionsService, times(1)).deletePermission(eq(inaf), eq("user_id"), eq(Permission.ADMIN)); + } + + @Test + public void testPrepareToJoin() throws Exception { + + PrepareToJoinRequest request = new PrepareToJoinRequest(); + request.setFromUserId("from_user"); + request.setToUserId("to_user"); + + mockMvc.perform(post("/ws/prepare-join") + .content(mapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()); + + verify(permissionsService, times(1)).movePermissions(request.getFromUserId(), request.getToUserId()); + verify(membersService, times(1)).moveMemberships(request.getFromUserId(), request.getToUserId()); + } + + private List<String> getNames(String... names) { + return Stream.of(names).collect(Collectors.toList()); + } + + private GroupEntity getInafGroup() { + GroupEntity inaf = new GroupEntity(); + inaf.setId("inaf_id"); + inaf.setName("INAF"); + inaf.setPath("lbt_id.inaf_id"); + return inaf; + } +} diff --git a/gms/src/test/java/it/inaf/ia2/gms/service/PermissionsServiceIntegrationTest.java b/gms/src/test/java/it/inaf/ia2/gms/service/PermissionsServiceIntegrationTest.java index fc04b4e..07be295 100644 --- a/gms/src/test/java/it/inaf/ia2/gms/service/PermissionsServiceIntegrationTest.java +++ b/gms/src/test/java/it/inaf/ia2/gms/service/PermissionsServiceIntegrationTest.java @@ -67,6 +67,6 @@ public class PermissionsServiceIntegrationTest { assertEquals(Permission.ADMIN, permissions.get(0).getPermission()); assertEquals(USER_ID, permissions.get(0).getUser().getId()); - permissionsService.deletePermission(USER_ID, GroupsService.ROOT, Permission.ADMIN); + permissionsService.deletePermission(root, USER_ID, Permission.ADMIN); } } -- GitLab