diff --git a/gms/pom.xml b/gms/pom.xml index 905ed512f1d9d1c2c876794f970b1019a092739e..f55c143b7ce58add20fcab7adaa2fac21c205a57 100644 --- a/gms/pom.xml +++ b/gms/pom.xml @@ -34,14 +34,14 @@ </dependency> <dependency> <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-jpa</artifactId> + <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> - <groupId>mysql</groupId> - <artifactId>mysql-connector-java</artifactId> + <groupId>org.postgresql</groupId> + <artifactId>postgresql</artifactId> + <version>42.2.6</version> <scope>runtime</scope> </dependency> - <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> @@ -58,11 +58,6 @@ <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> - <dependency> - <groupId>com.h2database</groupId> - <artifactId>h2</artifactId> - <scope>test</scope> - </dependency> <dependency> <groupId>io.zonky.test</groupId> <artifactId>embedded-database-spring-test</artifactId> diff --git a/gms/src/main/java/it/inaf/ia2/gms/authn/SessionData.java b/gms/src/main/java/it/inaf/ia2/gms/authn/SessionData.java index b3fd20a2c70990161d73aad9d88896f2d9b4c367..bc41752728384707944747b74b2b2991e5bee185 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/authn/SessionData.java +++ b/gms/src/main/java/it/inaf/ia2/gms/authn/SessionData.java @@ -1,7 +1,5 @@ package it.inaf.ia2.gms.authn; -import it.inaf.ia2.gms.persistence.UsersRepository; -import it.inaf.ia2.gms.persistence.model.User; import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; @@ -16,9 +14,6 @@ public class SessionData { @Autowired private HttpServletRequest request; - @Autowired - private UsersRepository usersRepository; - private String userId; private String accessToken; @@ -27,12 +22,6 @@ public class SessionData { CustomAuthenticationData authn = (CustomAuthenticationData) ((OAuth2Authentication) request.getUserPrincipal()).getUserAuthentication(); userId = (String) authn.getPrincipal(); accessToken = (String) authn.getAccessToken().getValue(); - - if (!usersRepository.findById(userId).isPresent()) { - User user = new User(); - user.setId(userId); - usersRepository.save(user); - } } public String getUserId() { 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 22c93cba30e72b0cdc68e467e421a213c8f37d79..8eb6f6469056335110af38d961de532da5d60067 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 @@ -8,12 +8,10 @@ import it.inaf.ia2.gms.model.GroupsModelResponse; import it.inaf.ia2.gms.model.PaginatedData; import it.inaf.ia2.gms.model.PaginatedModelRequest; import it.inaf.ia2.gms.model.RenameGroupRequest; -import it.inaf.ia2.gms.persistence.model.Group; -import it.inaf.ia2.gms.persistence.model.User; -import it.inaf.ia2.gms.service.GroupsModelService; +import it.inaf.ia2.gms.persistence.model.GroupEntity; +import it.inaf.ia2.gms.service.GroupsModelBuilder; import it.inaf.ia2.gms.service.GroupsService; -import it.inaf.ia2.gms.service.UsersService; -import java.util.List; +import it.inaf.ia2.gms.service.GroupsTreeBuilder; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -34,13 +32,13 @@ public class GroupsController { private SessionData session; @Autowired - private UsersService usersService; + private GroupsService groupsService; @Autowired - private GroupsModelService groupsModelService; + private GroupsModelBuilder groupsModelService; @Autowired - private GroupsService groupsService; + private GroupsTreeBuilder groupsTreeBuilder; @GetMapping(value = "/groups", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public GroupsModelResponse getGroupsModelResponse(@Valid GroupsModelRequest groupsModelRequest) { @@ -50,10 +48,9 @@ public class GroupsController { @PostMapping(value = "/group", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public ResponseEntity<PaginatedData<GroupNode>> createGroup(@Valid @RequestBody CreateGroupRequest request) { - User user = getUser(); - Group newGroup = groupsService.addGroup(request.getParentGroupId(), request.getNewGroupName(), user); + GroupEntity newGroup = groupsService.addGroup(request.getParentGroupId(), request.getNewGroupName(), session.getUserId()); - PaginatedData<GroupNode> groupsPanel = getGroupsPanel(newGroup.getParentGroup(), request, user); + PaginatedData<GroupNode> groupsPanel = getGroupsPanel(request.getParentGroupId(), request); return new ResponseEntity<>(groupsPanel, HttpStatus.CREATED); } @@ -61,10 +58,11 @@ public class GroupsController { @PutMapping(value = "/group/{groupId}", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public ResponseEntity<PaginatedData<GroupNode>> renameGroup(@PathVariable("groupId") String groupId, @Valid @RequestBody RenameGroupRequest request) { - User user = getUser(); - Group renamedGroup = groupsService.renameGroup(groupId, request.getNewGroupName(), user); + GroupEntity renamedGroup = groupsService.renameGroup(groupId, request.getNewGroupName(), session.getUserId()); + + GroupEntity parent = groupsService.getGroupByPath(renamedGroup.getParentPath()); - PaginatedData<GroupNode> groupsPanel = getGroupsPanel(renamedGroup.getParentGroup(), request, user); + PaginatedData<GroupNode> groupsPanel = getGroupsPanel(parent.getId(), request); return ResponseEntity.ok(groupsPanel); } @@ -72,20 +70,14 @@ 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) { - User user = getUser(); - Group parent = groupsService.deleteGroup(groupId, user); + GroupEntity parent = groupsService.deleteGroup(groupId, session.getUserId()); - PaginatedData<GroupNode> groupsPanel = getGroupsPanel(parent, request, user); + PaginatedData<GroupNode> groupsPanel = getGroupsPanel(parent.getId(), request); return ResponseEntity.ok(groupsPanel); } - private User getUser() { - return usersService.getUserById(session.getUserId()); - } - - private PaginatedData<GroupNode> getGroupsPanel(Group parentGroup, PaginatedModelRequest paginatedRequest, User user) { - List<GroupNode> groupNodes = groupsService.getSubgroups(parentGroup, user); - return new PaginatedData<>(groupNodes, paginatedRequest.getPaginatorPage(), paginatedRequest.getPaginatorPageSize()); + private PaginatedData<GroupNode> getGroupsPanel(String parentGroupId, PaginatedModelRequest paginatedRequest) { + return groupsTreeBuilder.listSubGroups(parentGroupId, session.getUserId(), paginatedRequest); } } diff --git a/gms/src/main/java/it/inaf/ia2/gms/controller/PermissionsController.java b/gms/src/main/java/it/inaf/ia2/gms/controller/PermissionsController.java index 4ae3d1c7674f485c7aca11da854dba00cf96845e..9c204e7165ce5fe2eddea59b1c491fd710d6722b 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/controller/PermissionsController.java +++ b/gms/src/main/java/it/inaf/ia2/gms/controller/PermissionsController.java @@ -2,9 +2,7 @@ package it.inaf.ia2.gms.controller; import it.inaf.ia2.gms.authn.SessionData; import it.inaf.ia2.gms.model.Permission; -import it.inaf.ia2.gms.persistence.model.User; import it.inaf.ia2.gms.service.PermissionsService; -import it.inaf.ia2.gms.service.UsersService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -18,19 +16,11 @@ public class PermissionsController { @Autowired private SessionData session; - @Autowired - private UsersService usersService; - @Autowired private PermissionsService permissionsService; @DeleteMapping(value = "/permission", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public ResponseEntity deletePermission(@RequestParam("user") String userId, @RequestParam("group") String group, @RequestParam("permission") Permission permission) { - User user = getUser(); return null; } - - private User getUser() { - return usersService.getUserById(session.getUserId()); - } } diff --git a/gms/src/main/java/it/inaf/ia2/gms/model/GroupNode.java b/gms/src/main/java/it/inaf/ia2/gms/model/GroupNode.java index 6ca71a1e443eb6815c707eb81837e026d6b15e57..cc1316b63a883462b2076762af6e523cc898cf5b 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/model/GroupNode.java +++ b/gms/src/main/java/it/inaf/ia2/gms/model/GroupNode.java @@ -1,22 +1,12 @@ package it.inaf.ia2.gms.model; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - public class GroupNode { private String groupId; private String groupName; - private Set<Permission> permissions; + private Permission permission; private boolean hasChildren; - public GroupNode() { - permissions = new HashSet<>(); - } - public String getGroupId() { return groupId; } @@ -33,44 +23,12 @@ public class GroupNode { this.groupName = groupName; } - public List<Permission> getPermissions() { - return Collections.unmodifiableList(new ArrayList<>(permissions)); + public Permission getPermission() { + return permission; } - public void setPermissions(Set<Permission> permissions) { - this.permissions = permissions; - } - - public void addPermission(Permission permission) { - - // remove implied permissions - switch (permission) { - case ADMIN: - permissions.add(permission); - permissions.remove(Permission.MANAGE_MEMBERS); - permissions.remove(Permission.VIEW_MEMBERS); - permissions.remove(Permission.TRAVERSE); - break; - case MANAGE_MEMBERS: - if (!permissions.contains(Permission.ADMIN)) { - permissions.add(permission); - permissions.remove(Permission.VIEW_MEMBERS); - permissions.remove(Permission.TRAVERSE); - } - break; - case VIEW_MEMBERS: - if (!permissions.contains(Permission.ADMIN) - && !permissions.contains(Permission.MANAGE_MEMBERS)) { - permissions.add(permission); - permissions.remove(Permission.TRAVERSE); - } - break; - case TRAVERSE: - if (permissions.isEmpty()) { - permissions.add(permission); - } - break; - } + public void setPermission(Permission permission) { + this.permission = permission; } public boolean isHasChildren() { diff --git a/gms/src/main/java/it/inaf/ia2/gms/model/GroupsModelResponse.java b/gms/src/main/java/it/inaf/ia2/gms/model/GroupsModelResponse.java index 415ff5cb6581babcd732768c0e3b7bc289da05b9..25cef046de7dc4e9e5ac878cc3156e61063e23e3 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/model/GroupsModelResponse.java +++ b/gms/src/main/java/it/inaf/ia2/gms/model/GroupsModelResponse.java @@ -9,7 +9,7 @@ public class GroupsModelResponse extends BaseModelResponse { private PaginatedData<RapUser> membersPanel; private PaginatedData<UserPermission> permissionsPanel; // current group permissions - private List<Permission> permissions; + private Permission permission; public List<GroupBreadcrumb> getBreadcrumbs() { return breadcrumbs; @@ -43,11 +43,11 @@ public class GroupsModelResponse extends BaseModelResponse { this.permissionsPanel = permissionsPanel; } - public List<Permission> getPermissions() { - return permissions; + public Permission getPermission() { + return permission; } - public void setPermissions(List<Permission> permissions) { - this.permissions = permissions; + public void setPermission(Permission permission) { + this.permission = permission; } } diff --git a/gms/src/main/java/it/inaf/ia2/gms/model/Permission.java b/gms/src/main/java/it/inaf/ia2/gms/model/Permission.java index be00ef7092d4e17163a7499e236f5f36a258672c..166c1dca96cdab6805537818694ff2dfacf5ca12 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/model/Permission.java +++ b/gms/src/main/java/it/inaf/ia2/gms/model/Permission.java @@ -5,5 +5,31 @@ public enum Permission { ADMIN, MANAGE_MEMBERS, VIEW_MEMBERS, - TRAVERSE + TRAVERSE; + + /** + * Updates the permission keeping the priority (e.g. MANAGE_MEMBERS + * overrides VIEW_MEMBERS, but not the opposite). + */ + public static Permission addPermission(Permission oldPermission, Permission newPermission) { + + if (oldPermission == null) { + return newPermission; + } + + switch (newPermission) { + case ADMIN: + return ADMIN; + case MANAGE_MEMBERS: + if (oldPermission != Permission.ADMIN) { + return MANAGE_MEMBERS; + } + case VIEW_MEMBERS: + if (oldPermission == Permission.TRAVERSE) { + return VIEW_MEMBERS; + } + } + + return oldPermission; + } } 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 f1109faa077d038f4649ac47627f677c5d5a64a6..5a38bca174501d226cbb5ec84846b7ded7e02023 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 @@ -1,12 +1,14 @@ package it.inaf.ia2.gms.persistence; -import it.inaf.ia2.gms.persistence.model.NewGroup; +import it.inaf.ia2.gms.model.GroupBreadcrumb; +import it.inaf.ia2.gms.persistence.model.GroupEntity; import java.sql.PreparedStatement; import java.sql.Types; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import javax.sql.DataSource; @@ -24,7 +26,7 @@ public class GroupsDAO { jdbcTemplate = new JdbcTemplate(dataSource); } - public NewGroup createGroup(NewGroup group) { + public GroupEntity createGroup(GroupEntity group) { String sql = "INSERT INTO gms_group (id, name, path) VALUES (?, ?, ?)"; @@ -39,12 +41,67 @@ public class GroupsDAO { return group; } + public GroupEntity updateGroup(GroupEntity group) { + + String sql = "UPDATE gms_group SET name = ?, path = ? WHERE id = ?"; + + jdbcTemplate.update(conn -> { + PreparedStatement ps = conn.prepareStatement(sql); + ps.setString(1, group.getName()); + ps.setObject(2, group.getPath(), Types.OTHER); + ps.setString(3, group.getId()); + return ps; + }); + + return group; + } + public void deleteGroupById(String groupId) { String sql = "DELETE FROM gms_group WHERE id = ?"; jdbcTemplate.update(sql, groupId); } - public List<NewGroup> listSubGroups(String path) { + public Optional<GroupEntity> findGroupById(String groupId) { + + String sql = "SELECT id, name, path from gms_group WHERE id = ?"; + + return jdbcTemplate.query(conn -> { + PreparedStatement ps = conn.prepareStatement(sql); + ps.setString(1, groupId); + return ps; + }, resultSet -> { + if (resultSet.next()) { + GroupEntity group = new GroupEntity(); + group.setId(resultSet.getString("id")); + group.setName(resultSet.getString("name")); + group.setPath(resultSet.getString("path")); + return Optional.of(group); + } + return Optional.empty(); + }); + } + + public Optional<GroupEntity> findGroupByPath(String path) { + + String sql = "SELECT id, name from gms_group WHERE path = ?"; + + return jdbcTemplate.query(conn -> { + PreparedStatement ps = conn.prepareStatement(sql); + ps.setObject(1, path, Types.OTHER); + return ps; + }, resultSet -> { + if (resultSet.next()) { + GroupEntity group = new GroupEntity(); + group.setId(resultSet.getString("id")); + group.setName(resultSet.getString("name")); + group.setPath(path); + return Optional.of(group); + } + return Optional.empty(); + }); + } + + public List<GroupEntity> listSubGroups(String path) { String sql = "SELECT id, name, path from gms_group WHERE path ~ ? ORDER BY name"; @@ -53,9 +110,9 @@ public class GroupsDAO { ps.setObject(1, getSubGroupsPath(path), Types.OTHER); return ps; }, resultSet -> { - List<NewGroup> groups = new ArrayList<>(); + List<GroupEntity> groups = new ArrayList<>(); while (resultSet.next()) { - NewGroup group = new NewGroup(); + GroupEntity group = new GroupEntity(); group.setId(resultSet.getString("id")); group.setName(resultSet.getString("name")); group.setPath(resultSet.getString("path")); @@ -98,4 +155,37 @@ public class GroupsDAO { return map; }); } + + /** + * Returns the number of groups. + */ + public long count() { + + String sql = "SELECT COUNT(*) FROM gms_group"; + + return jdbcTemplate.query(sql, resultSet -> { + resultSet.next(); + return resultSet.getLong(1); + }); + } + + public List<GroupBreadcrumb> getBreadcrumbs(String path) { + + String sql = "SELECT id, name FROM gms_group WHERE path @> ? ORDER BY length(path::varchar) ASC"; + + return jdbcTemplate.query(conn -> { + PreparedStatement ps = conn.prepareStatement(sql); + ps.setObject(1, path, Types.OTHER); + return ps; + }, resultSet -> { + List<GroupBreadcrumb> breadcrumbs = new ArrayList<>(); + while (resultSet.next()) { + GroupBreadcrumb bc = new GroupBreadcrumb(); + bc.setGroupId(resultSet.getString("id")); + bc.setGroupName(resultSet.getString("name")); + breadcrumbs.add(bc); + } + return breadcrumbs; + }); + } } diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/GroupsRepository.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/GroupsRepository.java deleted file mode 100644 index c7ad1eb1a6f4c06df8e121ab4e462fd76fe12548..0000000000000000000000000000000000000000 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/GroupsRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package it.inaf.ia2.gms.persistence; - -import it.inaf.ia2.gms.persistence.model.Group; -import java.util.List; -import javax.transaction.Transactional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -@Transactional -public interface GroupsRepository extends JpaRepository<Group, String> { - - List<Group> findByParentGroup(Group parent); -} diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/MembershipRepository.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/MembershipRepository.java deleted file mode 100644 index 44bd7df9128ae0afef56e2bb9baa2323960e2f9c..0000000000000000000000000000000000000000 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/MembershipRepository.java +++ /dev/null @@ -1,19 +0,0 @@ -package it.inaf.ia2.gms.persistence; - -import it.inaf.ia2.gms.persistence.model.Group; -import it.inaf.ia2.gms.persistence.model.Membership; -import it.inaf.ia2.gms.persistence.model.MembershipId; -import it.inaf.ia2.gms.persistence.model.User; -import java.util.List; -import javax.transaction.Transactional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -@Transactional -public interface MembershipRepository extends JpaRepository<Membership, MembershipId> { - - List<Membership> findBy_user(User user); - - List<Membership> findBy_group(Group group); -} 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 new file mode 100644 index 0000000000000000000000000000000000000000..d6b832dcf5c5336b5a6b627c9aa9c16d6c957731 --- /dev/null +++ b/gms/src/main/java/it/inaf/ia2/gms/persistence/MembershipsDAO.java @@ -0,0 +1,13 @@ +package it.inaf.ia2.gms.persistence; + +import it.inaf.ia2.gms.persistence.model.MembershipEntity; +import java.util.List; +import org.springframework.stereotype.Component; + +@Component +public class MembershipsDAO { + + public List<MembershipEntity> findByGroup(String groupId) { + throw new UnsupportedOperationException("TODO"); + } +} 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 0c4802278dc8ef30d9ea7bf14527fba94347581c..41621105f08311e0fea4122bf9611d4c7baff468 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 @@ -1,7 +1,7 @@ package it.inaf.ia2.gms.persistence; import it.inaf.ia2.gms.model.Permission; -import it.inaf.ia2.gms.persistence.model.UserPermission; +import it.inaf.ia2.gms.persistence.model.PermissionEntity; import java.sql.PreparedStatement; import java.sql.Types; import java.util.ArrayList; @@ -21,51 +21,100 @@ public class PermissionsDAO { jdbcTemplate = new JdbcTemplate(dataSource); } - public UserPermission createPermission(UserPermission userPermission) { + public PermissionEntity createPermission(PermissionEntity userPermission) { - String sql = "INSERT INTO gms_permission(group_id, user_id, permission) VALUES(?, ?, ?)"; + String sql = "INSERT INTO gms_permission(group_id, user_id, permission, group_path) VALUES(?, ?, ?, ?)"; jdbcTemplate.update(conn -> { PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, userPermission.getGroupId()); ps.setString(2, userPermission.getUserId()); ps.setObject(3, userPermission.getPermission().toString(), Types.OTHER); + ps.setObject(4, userPermission.getGroupPath(), Types.OTHER); return ps; }); return userPermission; } - public List<UserPermission> findUserPermissions(String userId) { + public List<PermissionEntity> findUserPermissions(String userId) { - String sql = "SELECT group_id, permission FROM gms_permission WHERE user_id = ?"; + String sql = "SELECT group_id, permission, group_path FROM gms_permission WHERE user_id = ?"; return jdbcTemplate.query(conn -> { PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, userId); return ps; }, resultSet -> { - List<UserPermission> permissions = new ArrayList<>(); + List<PermissionEntity> permissions = new ArrayList<>(); while (resultSet.next()) { - UserPermission permission = new UserPermission(); + PermissionEntity permission = new PermissionEntity(); permission.setGroupId(resultSet.getString("group_id")); permission.setUserId(userId); permission.setPermission(Permission.valueOf(resultSet.getString("permission"))); + permission.setGroupPath(resultSet.getString("group_path")); permissions.add(permission); } return permissions; }); } - public void deletePermission(UserPermission userPermission) { + public List<PermissionEntity> findUserPermissions(String userId, String path) { + + String sql = "SELECT group_id, permission, group_path FROM gms_permission WHERE user_id = ?\n" + + "AND (group_path <@ ? OR group_path @> ?)"; + + return jdbcTemplate.query(conn -> { + PreparedStatement ps = conn.prepareStatement(sql); + ps.setString(1, userId); + ps.setObject(2, path, Types.OTHER); + ps.setObject(3, path, Types.OTHER); + return ps; + }, resultSet -> { + List<PermissionEntity> permissions = new ArrayList<>(); + while (resultSet.next()) { + PermissionEntity permission = new PermissionEntity(); + permission.setGroupId(resultSet.getString("group_id")); + permission.setUserId(userId); + permission.setPermission(Permission.valueOf(resultSet.getString("permission"))); + permission.setGroupPath(resultSet.getString("group_path")); + permissions.add(permission); + } + return permissions; + }); + } + + public List<PermissionEntity> getGroupsPermissions(String groupId) { + + String sql = "SELECT user_id, permission, group_path FROM gms_permission WHERE group_id = ?"; + + return jdbcTemplate.query(conn -> { + PreparedStatement ps = conn.prepareStatement(sql); + ps.setString(1, groupId); + return ps; + }, resultSet -> { + List<PermissionEntity> permissions = new ArrayList<>(); + while (resultSet.next()) { + PermissionEntity permission = new PermissionEntity(); + permission.setGroupId(groupId); + permission.setUserId(resultSet.getString("user_id")); + permission.setPermission(Permission.valueOf(resultSet.getString("permission"))); + permission.setGroupPath(resultSet.getString("group_path")); + permissions.add(permission); + } + return permissions; + }); + } + + public void deletePermission(String groupId, String userId, Permission permission) { String sql = "DELETE FROM gms_permission WHERE group_id = ? AND user_id = ? AND permission = ?"; jdbcTemplate.update(conn -> { PreparedStatement ps = conn.prepareStatement(sql); - ps.setString(1, userPermission.getGroupId()); - ps.setString(2, userPermission.getUserId()); - ps.setObject(3, userPermission.getPermission().toString(), Types.OTHER); + ps.setString(1, groupId); + ps.setString(2, userId); + ps.setObject(3, permission.toString(), Types.OTHER); return ps; }); } diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/PermissionsRepository.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/PermissionsRepository.java deleted file mode 100644 index 9184992cb47e697b9d21ed6853ccfde3ace30a3e..0000000000000000000000000000000000000000 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/PermissionsRepository.java +++ /dev/null @@ -1,25 +0,0 @@ -package it.inaf.ia2.gms.persistence; - -import it.inaf.ia2.gms.model.Permission; -import it.inaf.ia2.gms.persistence.model.Group; -import it.inaf.ia2.gms.persistence.model.User; -import it.inaf.ia2.gms.persistence.model.UserGroupPermission; -import it.inaf.ia2.gms.persistence.model.UserGroupPermissionId; -import java.util.List; -import java.util.Optional; -import javax.transaction.Transactional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.stereotype.Repository; - -@Repository -@Transactional -public interface PermissionsRepository extends JpaRepository<UserGroupPermission, UserGroupPermissionId> { - - List<UserGroupPermission> findBy_user(User user); - - List<UserGroupPermission> findBy_group(Group group); - - @Query("SELECT u FROM UserGroupPermission u WHERE u._user.id = ?1 AND u._group.id = ?2 AND u.permission = ?3") - Optional<UserGroupPermission> findPermission(String userId, String groupId, Permission permission); -} diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/UsersRepository.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/UsersRepository.java deleted file mode 100644 index bf60c63ff38fe12288a75407874bbf70757a0533..0000000000000000000000000000000000000000 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/UsersRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package it.inaf.ia2.gms.persistence; - -import it.inaf.ia2.gms.persistence.model.User; -import javax.transaction.Transactional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -@Transactional -public interface UsersRepository extends JpaRepository<User, String> { -} diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/Group.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/Group.java deleted file mode 100644 index 504093e9d8e01965bcd6b3f5519a18ec6a911693..0000000000000000000000000000000000000000 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/Group.java +++ /dev/null @@ -1,95 +0,0 @@ -package it.inaf.ia2.gms.persistence.model; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.OrderBy; -import javax.persistence.Table; - -@Entity -@Table(name = "gms_group") -public class Group { - - @Id - @Column(length = 50) - private String id; - - @Column(nullable = false) - private String name; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "parent_group") - private Group parentGroup; - - @OneToMany(mappedBy = "parentGroup", fetch = FetchType.LAZY) - @OrderBy("name ASC") - private List<Group> childrenGroups; - - public Group() { - childrenGroups = new ArrayList<>(); - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Group getParentGroup() { - return parentGroup; - } - - public void setParentGroup(Group parentGroup) { - this.parentGroup = parentGroup; - } - - public List<Group> getChildrenGroups() { - return childrenGroups; - } - - public void setChildrenGroups(List<Group> childrenGroups) { - this.childrenGroups = childrenGroups; - } - - @Override - public int hashCode() { - int hash = 3; - hash = 89 * hash + Objects.hashCode(this.id); - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Group other = (Group) obj; - if (!Objects.equals(this.id, other.id)) { - return false; - } - return true; - } -} diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/GroupEntity.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/GroupEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..f0563e3b05cba107c1d74cbffaed31aa059f7c9b --- /dev/null +++ b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/GroupEntity.java @@ -0,0 +1,77 @@ +package it.inaf.ia2.gms.persistence.model; + +import java.util.Objects; + +public class GroupEntity { + + private String id; + private String name; + private String path; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getParentPath() { + if (path.isEmpty()) { + return null; + } + if (path.contains(".")) { + return path.substring(0, path.lastIndexOf(".")); + } + return ""; + } + + @Override + public int hashCode() { + int hash = 5; + hash = 79 * hash + Objects.hashCode(this.id); + hash = 79 * hash + Objects.hashCode(this.name); + hash = 79 * hash + Objects.hashCode(this.path); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final GroupEntity other = (GroupEntity) obj; + if (!Objects.equals(this.id, other.id)) { + return false; + } + if (!Objects.equals(this.name, other.name)) { + return false; + } + if (!Objects.equals(this.path, other.path)) { + return false; + } + return true; + } +} diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/Membership.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/Membership.java deleted file mode 100644 index 69b282fb2301558124ca29dbe4bff2b5d5ecf4ea..0000000000000000000000000000000000000000 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/Membership.java +++ /dev/null @@ -1,44 +0,0 @@ -package it.inaf.ia2.gms.persistence.model; - -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.IdClass; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.Table; - -/** - * Note: if necessary this class could contain also a role (specific for the - * application using the GMS). Currently that is not implemented. - */ -@Entity -@IdClass(MembershipId.class) -@Table(name = "gms_membership") -public class Membership { - - @Id - @ManyToOne - @JoinColumn(name = "user_id", referencedColumnName = "id", columnDefinition = "varchar(50)") - private User _user; - - @Id - @ManyToOne - @JoinColumn(name = "group_id", referencedColumnName = "id", columnDefinition = "varchar(50)") - private Group _group; - - public User getUser() { - return _user; - } - - public void setUser(User _user) { - this._user = _user; - } - - public Group getGroup() { - return _group; - } - - public void setGroup(Group _group) { - this._group = _group; - } -} 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 new file mode 100644 index 0000000000000000000000000000000000000000..9625a8706842442d639756bd103e662f74c098da --- /dev/null +++ b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/MembershipEntity.java @@ -0,0 +1,23 @@ +package it.inaf.ia2.gms.persistence.model; + +public class MembershipEntity { + + private String groupId; + 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/persistence/model/MembershipId.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/MembershipId.java deleted file mode 100644 index c0b1beab333ce7e7304a0f52b361f778a3be0a96..0000000000000000000000000000000000000000 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/MembershipId.java +++ /dev/null @@ -1,39 +0,0 @@ -package it.inaf.ia2.gms.persistence.model; - -import java.io.Serializable; -import java.util.Objects; - -public class MembershipId implements Serializable { - - String _user; - String _group; - - @Override - public int hashCode() { - int hash = 7; - hash = 47 * hash + Objects.hashCode(this._user); - hash = 47 * hash + Objects.hashCode(this._group); - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final MembershipId other = (MembershipId) obj; - if (!Objects.equals(this._user, other._user)) { - return false; - } - if (!Objects.equals(this._group, other._group)) { - return false; - } - return true; - } -} diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/UserPermission.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/PermissionEntity.java similarity index 69% rename from gms/src/main/java/it/inaf/ia2/gms/persistence/model/UserPermission.java rename to gms/src/main/java/it/inaf/ia2/gms/persistence/model/PermissionEntity.java index 6d1e8394164918bfbcfd6748e2fddef395e68a8c..957e658c246bc0dde4063d358f8e417ec38e34fc 100644 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/UserPermission.java +++ b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/PermissionEntity.java @@ -2,11 +2,14 @@ package it.inaf.ia2.gms.persistence.model; import it.inaf.ia2.gms.model.Permission; -public class UserPermission { +public class PermissionEntity { private String userId; private String groupId; private Permission permission; + + // The group path is copied here for performance reasons + private String groupPath; public String getUserId() { return userId; @@ -31,4 +34,12 @@ public class UserPermission { public void setPermission(Permission permission) { this.permission = permission; } + + public String getGroupPath() { + return groupPath; + } + + public void setGroupPath(String groupPath) { + this.groupPath = groupPath; + } } diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/User.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/User.java deleted file mode 100644 index 9d2c6d794ea996c48cc2b9158beee2153810d051..0000000000000000000000000000000000000000 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/User.java +++ /dev/null @@ -1,23 +0,0 @@ -package it.inaf.ia2.gms.persistence.model; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; - -@Entity -@Table(name = "gms_user") -public class User { - - @Id - @Column(length = 50) - private String id; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } -} diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/UserGroupPermission.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/UserGroupPermission.java deleted file mode 100644 index 3eebc85e7502d3a38958156628cf6e179cd5dce6..0000000000000000000000000000000000000000 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/UserGroupPermission.java +++ /dev/null @@ -1,95 +0,0 @@ -package it.inaf.ia2.gms.persistence.model; - -import it.inaf.ia2.gms.model.Permission; -import java.util.Objects; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Id; -import javax.persistence.IdClass; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.Table; - -/** - * NOTE: underscores in variable names are used when a field is a reserved JPQL - * keyword. - */ -@Entity -@IdClass(UserGroupPermissionId.class) -@Table(name = "gms_user_group_permission") -public class UserGroupPermission { - - @Id - @ManyToOne - @JoinColumn(name = "user_id", referencedColumnName = "id", columnDefinition = "varchar(50)") - private User _user; - - @Id - @ManyToOne - @JoinColumn(name = "group_id", referencedColumnName = "id", columnDefinition = "varchar(50)") - private Group _group; - - @Id - @Enumerated(EnumType.STRING) - @Column(name = "permission", length = 50) - private Permission permission; - - public User getUser() { - return _user; - } - - public void setUser(User user) { - this._user = user; - } - - public Group getGroup() { - return _group; - } - - public void setGroup(Group group) { - this._group = group; - } - - public Permission getPermission() { - return permission; - } - - public void setPermission(Permission permission) { - this.permission = permission; - } - - @Override - public int hashCode() { - int hash = 7; - hash = 47 * hash + Objects.hashCode(this._user); - hash = 47 * hash + Objects.hashCode(this._group); - hash = 47 * hash + Objects.hashCode(this.permission); - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final UserGroupPermission other = (UserGroupPermission) obj; - if (!Objects.equals(this._user, other._user)) { - return false; - } - if (!Objects.equals(this._group, other._group)) { - return false; - } - if (this.permission != other.permission) { - return false; - } - return true; - } -} diff --git a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/UserGroupPermissionId.java b/gms/src/main/java/it/inaf/ia2/gms/persistence/model/UserGroupPermissionId.java deleted file mode 100644 index c036bfd25d7d228207653a385e59b5f02574adf0..0000000000000000000000000000000000000000 --- a/gms/src/main/java/it/inaf/ia2/gms/persistence/model/UserGroupPermissionId.java +++ /dev/null @@ -1,45 +0,0 @@ -package it.inaf.ia2.gms.persistence.model; - -import it.inaf.ia2.gms.model.Permission; -import java.io.Serializable; -import java.util.Objects; - -public class UserGroupPermissionId implements Serializable { - - String _user; - String _group; - Permission permission; - - @Override - public int hashCode() { - int hash = 5; - hash = 71 * hash + Objects.hashCode(this._user); - hash = 71 * hash + Objects.hashCode(this._group); - hash = 71 * hash + Objects.hashCode(this.permission); - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final UserGroupPermissionId other = (UserGroupPermissionId) obj; - if (!Objects.equals(this._user, other._user)) { - return false; - } - if (!Objects.equals(this._group, other._group)) { - return false; - } - if (this.permission != other.permission) { - return false; - } - return true; - } -} diff --git a/gms/src/main/java/it/inaf/ia2/gms/service/GroupsModelBuilder.java b/gms/src/main/java/it/inaf/ia2/gms/service/GroupsModelBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..f47426daf030357e14cdf6ddd3bd355f80d38817 --- /dev/null +++ b/gms/src/main/java/it/inaf/ia2/gms/service/GroupsModelBuilder.java @@ -0,0 +1,62 @@ +package it.inaf.ia2.gms.service; + +import it.inaf.ia2.gms.model.GroupsModelRequest; +import it.inaf.ia2.gms.model.GroupsModelResponse; +import it.inaf.ia2.gms.model.PaginatedData; +import it.inaf.ia2.gms.model.Permission; +import it.inaf.ia2.gms.model.RapUser; +import it.inaf.ia2.gms.model.UserPermission; +import it.inaf.ia2.gms.persistence.model.GroupEntity; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class GroupsModelBuilder { + + @Autowired + private GroupsService groupsService; + + @Autowired + private GroupsTreeBuilder groupsTreeBuilder; + + @Autowired + private MembersService membersService; + + @Autowired + private PermissionsService permissionsService; + + public GroupsModelResponse getGroupsModel(GroupsModelRequest request, String userId) { + + GroupEntity group = groupsService.getGroupById(request.getGroupId()); + + GroupsModelResponse response = new GroupsModelResponse(); + + response.setPage("groups"); + + response.setBreadcrumbs(groupsService.getBreadcrumbs(group.getPath())); + + Permission currentNodePermissions = permissionsService.getGroupPermission(group, userId); + response.setPermission(currentNodePermissions); + + switch (request.getTab()) { + case "groups": + response.setGroupsPanel(groupsTreeBuilder.listSubGroups(group.getId(), userId, request)); + break; + case "members": + if (currentNodePermissions != Permission.TRAVERSE) { + List<RapUser> members = membersService.getMembers(group.getId()); + response.setMembersPanel(new PaginatedData<>(members, request.getPaginatorPage(), request.getPaginatorPageSize())); + } + break; + case "permissions": + if (currentNodePermissions == Permission.ADMIN) { + List<UserPermission> permissions = permissionsService.getUserPermissions(group); + response.setPermissionsPanel(new PaginatedData<>(permissions, request.getPaginatorPage(), request.getPaginatorPageSize())); + } + break; + } + + return response; + } +} diff --git a/gms/src/main/java/it/inaf/ia2/gms/service/GroupsModelService.java b/gms/src/main/java/it/inaf/ia2/gms/service/GroupsModelService.java deleted file mode 100644 index 813e1710d7c7255e677976542ba218c363bc3abe..0000000000000000000000000000000000000000 --- a/gms/src/main/java/it/inaf/ia2/gms/service/GroupsModelService.java +++ /dev/null @@ -1,86 +0,0 @@ -package it.inaf.ia2.gms.service; - -import it.inaf.ia2.gms.model.GroupBreadcrumb; -import it.inaf.ia2.gms.model.GroupNode; -import it.inaf.ia2.gms.model.GroupsModelRequest; -import it.inaf.ia2.gms.model.GroupsModelResponse; -import it.inaf.ia2.gms.model.PaginatedData; -import it.inaf.ia2.gms.model.Permission; -import it.inaf.ia2.gms.model.RapUser; -import it.inaf.ia2.gms.model.UserPermission; -import it.inaf.ia2.gms.persistence.model.Group; -import it.inaf.ia2.gms.persistence.model.User; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class GroupsModelService { - - @Autowired - private UsersService usersService; - - @Autowired - private GroupsService groupsService; - - @Autowired - private MembersService membersService; - - @Autowired - private PermissionsService permissionsService; - - public GroupsModelResponse getGroupsModel(GroupsModelRequest request, String userId) { - - User user = usersService.getUserById(userId); - Group group = groupsService.getGroupById(request.getGroupId()); - - GroupsModelResponse response = new GroupsModelResponse(); - - response.setPage("groups"); - - response.setBreadcrumbs(buildBreadcrumbs(new ArrayList<>(), group)); - - List<Permission> currentNodePermissions = groupsService.getPermissions(group, user); - response.setPermissions(currentNodePermissions); - - switch (request.getTab()) { - case "groups": - List<GroupNode> groupNodes = groupsService.getSubgroups(group, user); - response.setGroupsPanel(new PaginatedData<>(groupNodes, request.getPaginatorPage(), request.getPaginatorPageSize())); - break; - case "members": - if (currentNodePermissions.contains(Permission.ADMIN) - || currentNodePermissions.contains(Permission.MANAGE_MEMBERS) - || currentNodePermissions.contains(Permission.VIEW_MEMBERS)) { - List<RapUser> members = membersService.getMembers(group); - response.setMembersPanel(new PaginatedData<>(members, request.getPaginatorPage(), request.getPaginatorPageSize())); - } - break; - case "permissions": - if (currentNodePermissions.contains(Permission.ADMIN)) { - List<UserPermission> permissions = permissionsService.getUserPermissions(group); - response.setPermissionsPanel(new PaginatedData<>(permissions, request.getPaginatorPage(), request.getPaginatorPageSize())); - } - break; - } - - return response; - } - - private List<GroupBreadcrumb> buildBreadcrumbs(List<GroupBreadcrumb> breadcrumbs, Group group) { - - GroupBreadcrumb bc = new GroupBreadcrumb(); - bc.setGroupId(group.getId()); - bc.setGroupName(group.getName()); - breadcrumbs.add(bc); - - if (group.getParentGroup() == null) { - Collections.reverse(breadcrumbs); - return breadcrumbs; - } else { - return buildBreadcrumbs(breadcrumbs, group.getParentGroup()); - } - } -} 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 c82324af529a173586df1a9a256acbf0cd842454..15ad515678f6652f74b53e135511d5571aeabe41 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 @@ -2,21 +2,13 @@ package it.inaf.ia2.gms.service; import it.inaf.ia2.gms.exception.BadRequestException; import it.inaf.ia2.gms.exception.UnauthorizedException; -import it.inaf.ia2.gms.persistence.GroupsRepository; -import it.inaf.ia2.gms.persistence.MembershipRepository; -import it.inaf.ia2.gms.persistence.model.Group; -import it.inaf.ia2.gms.persistence.model.User; -import it.inaf.ia2.gms.persistence.model.UserGroupPermission; -import java.util.List; +import it.inaf.ia2.gms.model.GroupBreadcrumb; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import it.inaf.ia2.gms.persistence.PermissionsRepository; -import it.inaf.ia2.gms.persistence.model.Membership; -import it.inaf.ia2.gms.model.GroupNode; import it.inaf.ia2.gms.model.Permission; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; +import it.inaf.ia2.gms.persistence.GroupsDAO; +import it.inaf.ia2.gms.persistence.model.GroupEntity; +import java.util.List; import java.util.UUID; import org.springframework.transaction.annotation.Transactional; @@ -25,75 +17,82 @@ public class GroupsService { public static final String ROOT = "ROOT"; - private final GroupsRepository groupsRepository; - private final PermissionsRepository permissionsRepository; - private final MembershipRepository membershipRepository; + private final GroupsDAO groupsDAO; + private final PermissionsService permissionsService; @Autowired - public GroupsService(GroupsRepository groupsRepository, - PermissionsRepository permissionsRepository, - MembershipRepository membershipRepository) { - this.groupsRepository = groupsRepository; - this.permissionsRepository = permissionsRepository; - this.membershipRepository = membershipRepository; + public GroupsService(GroupsDAO groupsDAO, + PermissionsService permissionsService) { + this.groupsDAO = groupsDAO; + this.permissionsService = permissionsService; createRootIfNecessary(); } private void createRootIfNecessary() { - if (groupsRepository.count() == 0) { - Group root = new Group(); + if (groupsDAO.count() == 0) { + GroupEntity root = new GroupEntity(); root.setId(ROOT); root.setName(ROOT); - groupsRepository.save(root); + root.setPath(""); + groupsDAO.createGroup(root); } } @Transactional - public Group addGroup(String parentId, String groupName, User user) { + public GroupEntity addGroup(String parentId, String groupName, String userId) { - Group parent = getGroupById(parentId); + GroupEntity parent = getGroupById(parentId); - if (!getPermissions(parent, user).contains(Permission.ADMIN)) { + if (permissionsService.getGroupPermission(parent, userId) != Permission.ADMIN) { throw new UnauthorizedException("Missing admin privileges"); } - if (parent.getChildrenGroups().stream() + if (groupsDAO.listSubGroups(parent.getPath()).stream() .anyMatch(g -> g.getName().equals(groupName))) { throw new BadRequestException("There is already a group named " + groupName); } - Group group = new Group(); - group.setId(UUID.randomUUID().toString()); + String newGroupId = UUID.randomUUID().toString(); + + String path = parent.getPath(); + if (!path.isEmpty()) { + path += "."; + } + path += newGroupId; + + GroupEntity group = new GroupEntity(); + group.setId(newGroupId); group.setName(groupName); - group.setParentGroup(parent); - parent.getChildrenGroups().add(group); - group = groupsRepository.save(group); - groupsRepository.save(parent); + group.setPath(path); + + groupsDAO.createGroup(group); + return group; } - public Group renameGroup(String groupId, String newGroupName, User user) { + public GroupEntity renameGroup(String groupId, String newGroupName, String userId) { - Group group = getGroupById(groupId); + GroupEntity group = getGroupById(groupId); - if (!getPermissions(group, user).contains(Permission.ADMIN)) { + if (permissionsService.getGroupPermission(group, userId) != Permission.ADMIN) { throw new UnauthorizedException("Missing admin privileges"); } - if (group.getParentGroup().getChildrenGroups().stream() + if (groupsDAO.listSubGroups(group.getPath()).stream() .anyMatch(g -> g.getName().equals(newGroupName))) { throw new BadRequestException("There is already a group named " + newGroupName); } group.setName(newGroupName); - return groupsRepository.save(group); + + return groupsDAO.updateGroup(group); } - public Group deleteGroup(String groupId, User user) { + public GroupEntity deleteGroup(String groupId, String userId) { - Group group = getGroupById(groupId); + GroupEntity group = getGroupById(groupId); - if (!getPermissions(group, user).contains(Permission.ADMIN)) { + if (permissionsService.getGroupPermission(group, userId) != Permission.ADMIN) { throw new UnauthorizedException("Missing admin privileges"); } @@ -101,130 +100,26 @@ public class GroupsService { throw new UnauthorizedException("It is not possible to remove the ROOT"); } - Group parent = group.getParentGroup(); - - groupsRepository.delete(group); - - return parent; - } - - @Transactional - public List<GroupNode> getSubgroups(Group parent, User user) { - - List<UserGroupPermission> permissions = getAllPermissions(user); - - Map<String, GroupNode> nodesMap = new HashMap<>(); - - for (Group childGroup : parent.getChildrenGroups()) { - addGroupNodeToMap(childGroup, permissions, nodesMap); - } - - List<GroupNode> nodes = new ArrayList<>(nodesMap.values()); - - // Sort by group name - nodes.sort((n1, n2) -> n1.getGroupName().compareTo(n2.getGroupName())); - - return nodes; - } - - public List<Permission> getPermissions(Group group, User user) { - - List<UserGroupPermission> permissions = getAllPermissions(user); - Map<String, GroupNode> nodesMap = new HashMap<>(); - - addGroupNodeToMap(group, permissions, nodesMap); - - GroupNode groupNode = nodesMap.get(group.getId()); - if (groupNode == null) { - return new ArrayList<>(); - } - return groupNode.getPermissions(); - } - - /** - * Returns all the permissions, including also the calculated ones (the ones - * derived from the memberships). - */ - private List<UserGroupPermission> getAllPermissions(User user) { - - // explicit permissions - List<UserGroupPermission> permissions = permissionsRepository.findBy_user(user); - - List<UserGroupPermission> implicitPermissions = new ArrayList<>(); - for (Membership membership : membershipRepository.findBy_user(user)) { - UserGroupPermission userGroupPermission = new UserGroupPermission(); - userGroupPermission.setUser(user); - userGroupPermission.setGroup(membership.getGroup()); - userGroupPermission.setPermission(Permission.TRAVERSE); - implicitPermissions.add(userGroupPermission); - } - - permissions.addAll(implicitPermissions); - return permissions; - } - - private void addGroupNodeToMap(Group group, List<UserGroupPermission> permissions, Map<String, GroupNode> nodesMap) { - - for (UserGroupPermission permission : permissions) { - - boolean isChild = false; - if (permission.getGroup().getId().equals(group.getId()) - || (isChild = isChildOf(permission.getGroup(), group)) - || (isParentOf(permission.getGroup(), group))) { + String parentPath = group.getParentPath(); + GroupEntity parent = groupsDAO.findGroupByPath(parentPath) + .orElseThrow(() -> new BadRequestException("No group found at path " + parentPath)); - GroupNode node = nodesMap.get(group.getId()); - if (node == null) { - node = getGroupNode(group); - } + groupsDAO.deleteGroupById(groupId); - if (isChild) { - // Traversal only - node.addPermission(Permission.TRAVERSE); - } else { - // Direct permission or permission inherited from parent - node.addPermission(permission.getPermission()); - } - - nodesMap.put(group.getId(), node); - } - } - } - - private GroupNode getGroupNode(Group group) { - GroupNode node = new GroupNode(); - node.setGroupId(group.getId()); - node.setGroupName(group.getName()); - node.setHasChildren(!group.getChildrenGroups().isEmpty()); - return node; + return parent; } - private boolean isChildOf(Group group, Group possibleParent) { - Group parent = group.getParentGroup(); - if (parent == null) { - // ROOT has no parent - return false; - } - if (possibleParent.getId().equals(parent.getId())) { - return true; - } - // recursive call to parent group - return isChildOf(parent, possibleParent); + public GroupEntity getGroupById(String groupId) { + return groupsDAO.findGroupById(groupId) + .orElseThrow(() -> new BadRequestException("Group " + groupId + " not found")); } - private boolean isParentOf(Group group, Group possibleChild) { - Group parent = possibleChild.getParentGroup(); - if (parent == null) { - return false; - } - if (parent.getId().equals(group.getId())) { - return true; - } - // recursive call to parent group - return isParentOf(group, parent); + public GroupEntity getGroupByPath(String path) { + return groupsDAO.findGroupByPath(path) + .orElseThrow(() -> new BadRequestException("Group not found at path " + path)); } - public Group getGroupById(String groupId) { - return groupsRepository.findById(groupId) - .orElseThrow(() -> new BadRequestException("Group " + groupId + " not found")); + public List<GroupBreadcrumb> getBreadcrumbs(String path) { + return groupsDAO.getBreadcrumbs(path); } } diff --git a/gms/src/main/java/it/inaf/ia2/gms/service/GroupsTreeBuilder.java b/gms/src/main/java/it/inaf/ia2/gms/service/GroupsTreeBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..f431bf6fdc9707d5afead94c630146a4212da6cb --- /dev/null +++ b/gms/src/main/java/it/inaf/ia2/gms/service/GroupsTreeBuilder.java @@ -0,0 +1,82 @@ +package it.inaf.ia2.gms.service; + +import it.inaf.ia2.gms.exception.BadRequestException; +import it.inaf.ia2.gms.model.GroupNode; +import it.inaf.ia2.gms.model.PaginatedData; +import it.inaf.ia2.gms.model.PaginatedModelRequest; +import it.inaf.ia2.gms.persistence.GroupsDAO; +import it.inaf.ia2.gms.persistence.PermissionsDAO; +import it.inaf.ia2.gms.persistence.model.GroupEntity; +import it.inaf.ia2.gms.persistence.model.PermissionEntity; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class GroupsTreeBuilder { + + private final GroupsDAO groupsDAO; + private final PermissionsDAO permissionsDAO; + + @Autowired + public GroupsTreeBuilder(GroupsDAO groupsDAO, PermissionsDAO permissionsDAO) { + this.groupsDAO = groupsDAO; + this.permissionsDAO = permissionsDAO; + } + + public PaginatedData<GroupNode> listSubGroups(String parentGroupId, String userId, PaginatedModelRequest paginatedModelRequest) { + + GroupEntity parent = groupsDAO.findGroupById(parentGroupId) + .orElseThrow(() -> new BadRequestException("Group " + parentGroupId + " not found")); + + // All the sub groups of given parent + List<GroupEntity> allGroups = groupsDAO.listSubGroups(parent.getPath()); + + // Select only the groups visible to the user + List<PermissionEntity> permissions = permissionsDAO.findUserPermissions(userId); + List<GroupNode> userGroups = filterOnPermissions(allGroups, permissions); + + PaginatedData<GroupNode> paginatedGroups = new PaginatedData<>(userGroups, + paginatedModelRequest.getPaginatorPage(), paginatedModelRequest.getPaginatorPageSize()); + + fillHasChildrenFlags(paginatedGroups.getItems()); + + return paginatedGroups; + } + + private List<GroupNode> filterOnPermissions(List<GroupEntity> allGroups, List<PermissionEntity> permissions) { + + List<GroupNode> nodes = new ArrayList<>(); + + for (GroupEntity group : allGroups) { + + PermissionUtils.getGroupPermission(group, permissions).ifPresent(permission -> { + + GroupNode node = new GroupNode(); + node.setGroupId(group.getId()); + node.setGroupName(group.getName()); + node.setPermission(permission); + nodes.add(node); + }); + } + + // Sort by group name + nodes.sort((n1, n2) -> n1.getGroupName().compareTo(n2.getGroupName())); + return nodes; + } + + private void fillHasChildrenFlags(List<GroupNode> groups) { + + Set<String> groupIds = groups.stream().map(g -> g.getGroupId()).collect(Collectors.toSet()); + + Map<String, Boolean> hasChildrenMap = groupsDAO.getHasChildrenMap(groupIds); + + for (GroupNode group : groups) { + group.setHasChildren(hasChildrenMap.get(group.getGroupId())); + } + } +} 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 5e1b5a045465ebc54dd9d61c8b52fdc74b96f859..7f9ab1d551715262fa49c9bfe7eb889f5315b5a2 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 @@ -1,9 +1,8 @@ package it.inaf.ia2.gms.service; import it.inaf.ia2.gms.model.RapUser; -import it.inaf.ia2.gms.persistence.MembershipRepository; -import it.inaf.ia2.gms.persistence.model.Group; -import it.inaf.ia2.gms.persistence.model.Membership; +import it.inaf.ia2.gms.persistence.MembershipsDAO; +import it.inaf.ia2.gms.persistence.model.MembershipEntity; import it.inaf.ia2.gms.rap.RapClient; import java.util.List; import java.util.Set; @@ -15,16 +14,17 @@ import org.springframework.stereotype.Service; public class MembersService { @Autowired - private MembershipRepository membershipRepository; + private MembershipsDAO membershipsDAO; @Autowired private RapClient rapClient; - public List<RapUser> getMembers(Group group) { - List<Membership> memberships = membershipRepository.findBy_group(group); + public List<RapUser> getMembers(String groupId) { + + List<MembershipEntity> memberships = membershipsDAO.findByGroup(groupId); Set<String> userIdentifiers = memberships.stream() - .map(m -> m.getUser().getId()) + .map(m -> m.getUserId()) .collect(Collectors.toSet()); return rapClient.getUsers(userIdentifiers); diff --git a/gms/src/main/java/it/inaf/ia2/gms/service/PermissionUtils.java b/gms/src/main/java/it/inaf/ia2/gms/service/PermissionUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..a4d877abfea8f216503862a9b02c1b3877b44e4c --- /dev/null +++ b/gms/src/main/java/it/inaf/ia2/gms/service/PermissionUtils.java @@ -0,0 +1,40 @@ +package it.inaf.ia2.gms.service; + +import it.inaf.ia2.gms.model.Permission; +import it.inaf.ia2.gms.persistence.model.GroupEntity; +import it.inaf.ia2.gms.persistence.model.PermissionEntity; +import java.util.List; +import java.util.Optional; + +public class PermissionUtils { + + public static Optional<Permission> getGroupPermission(GroupEntity group, List<PermissionEntity> permissions) { + + Permission groupPermission = null; + + for (PermissionEntity permission : permissions) { + + boolean directPermission = permission.getGroupId().equals(group.getId()); + boolean permissionInChildGroup = permission.getGroupPath().startsWith(group.getPath()); + boolean permissionInParentGroup = group.getPath().startsWith(permission.getGroupPath()); + + if (directPermission || permissionInChildGroup || permissionInParentGroup) { + + if (permissionInChildGroup) { + // Traversal only + groupPermission = Permission.addPermission(groupPermission, Permission.TRAVERSE); + } else { + // Direct permission or permission inherited from parent + groupPermission = Permission.addPermission(groupPermission, permission.getPermission()); + } + } + + if (groupPermission == Permission.ADMIN) { + // reached the maximum permission + break; + } + } + + return Optional.ofNullable(groupPermission); + } +} 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 1a8d6436e66aacf3aa045b6df2a207df2b7cbd93..ad1f5a90791ce92850983fe91bddc2b21e99b4d4 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 @@ -1,12 +1,11 @@ package it.inaf.ia2.gms.service; -import it.inaf.ia2.gms.exception.BadRequestException; import it.inaf.ia2.gms.model.Permission; import it.inaf.ia2.gms.model.RapUser; import it.inaf.ia2.gms.model.UserPermission; -import it.inaf.ia2.gms.persistence.PermissionsRepository; -import it.inaf.ia2.gms.persistence.model.Group; -import it.inaf.ia2.gms.persistence.model.UserGroupPermission; +import it.inaf.ia2.gms.persistence.model.PermissionEntity; +import it.inaf.ia2.gms.persistence.PermissionsDAO; +import it.inaf.ia2.gms.persistence.model.GroupEntity; import it.inaf.ia2.gms.rap.RapClient; import java.util.ArrayList; import java.util.List; @@ -20,21 +19,21 @@ import org.springframework.stereotype.Service; @Service public class PermissionsService { - private final PermissionsRepository permissionsRepository; + private final PermissionsDAO permissionsDAO; private final RapClient rapClient; @Autowired - public PermissionsService(PermissionsRepository permissionsRepository, RapClient rapClient) { - this.permissionsRepository = permissionsRepository; + public PermissionsService(PermissionsDAO permissionsDAO, RapClient rapClient) { + this.permissionsDAO = permissionsDAO; this.rapClient = rapClient; } - public List<UserPermission> getUserPermissions(Group group) { + public List<UserPermission> getUserPermissions(GroupEntity group) { - List<UserGroupPermission> permissions = permissionsRepository.findBy_group(group); + List<PermissionEntity> permissions = permissionsDAO.getGroupsPermissions(group.getId()); Set<String> userIdentifiers = permissions.stream() - .map(p -> p.getUser().getId()) + .map(p -> p.getUserId()) .collect(Collectors.toSet()); Map<String, RapUser> users = rapClient.getUsers(userIdentifiers).stream() @@ -42,8 +41,8 @@ public class PermissionsService { List<UserPermission> result = new ArrayList<>(); - for (UserGroupPermission p : permissions) { - RapUser rapUser = users.get(p.getUser().getId()); + for (PermissionEntity p : permissions) { + RapUser rapUser = users.get(p.getUserId()); if (rapUser != null) { UserPermission permission = new UserPermission(); permission.setPermission(p.getPermission()); @@ -55,12 +54,12 @@ public class PermissionsService { return result; } - public void deletePermission(String userId, String groupId, Permission permission) { - - UserGroupPermission ugp = permissionsRepository.findPermission(userId, groupId, permission) - .orElseThrow(() -> new BadRequestException("Permission not found (UserId=" - + userId + ", GroupId=" + groupId + ", Permission=" + permission + ")")); + public Permission getGroupPermission(GroupEntity group, String userId) { + List<PermissionEntity> permissions = permissionsDAO.findUserPermissions(userId, group.getPath()); + return PermissionUtils.getGroupPermission(group, permissions).orElse(null); + } - permissionsRepository.delete(ugp); + public void deletePermission(String userId, String groupId, Permission permission) { + permissionsDAO.deletePermission(userId, groupId, permission); } } diff --git a/gms/src/main/java/it/inaf/ia2/gms/service/UsersService.java b/gms/src/main/java/it/inaf/ia2/gms/service/UsersService.java deleted file mode 100644 index 3cf6a9905b82d8ced1582d1cbcf28ae827a0c5b1..0000000000000000000000000000000000000000 --- a/gms/src/main/java/it/inaf/ia2/gms/service/UsersService.java +++ /dev/null @@ -1,24 +0,0 @@ -package it.inaf.ia2.gms.service; - -import it.inaf.ia2.gms.exception.BadRequestException; -import it.inaf.ia2.gms.persistence.UsersRepository; -import it.inaf.ia2.gms.persistence.model.User; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class UsersService { - - private final UsersRepository usersRepository; - - @Autowired - public UsersService(UsersRepository usersRepository) { - this.usersRepository = usersRepository; - } - - public User getUserById(String userId) { - - return usersRepository.findById(userId) - .orElseThrow(() -> new BadRequestException("User " + userId + " not found")); - } -} diff --git a/gms/src/main/resources/application.properties b/gms/src/main/resources/application.properties index 2f8ac50a1b54e5f22f17883db1f012879f7fb990..c92e337f53978e2ee80a674e1e4a0a1a84cba475 100644 --- a/gms/src/main/resources/application.properties +++ b/gms/src/main/resources/application.properties @@ -9,6 +9,7 @@ security.oauth2.client.scope=openid,email,profile security.oauth2.resource.jwk.key-set-uri=http://localhost/rap-ia2/auth/oidc/jwks logging.level.org.springframework.security=DEBUG +logging.level.org.springframework.jdbc=TRACE spring.jpa.hibernate.ddl-auto=update spring.jpa.database-platform=org.hibernate.dialect.MariaDBDialect diff --git a/gms/src/main/resources/sql/init.sql b/gms/src/main/resources/sql/init.sql index 780ce0ebcb33c4c2038b854d5eb64198c31c4903..737c319d7d89f20011eef0c176823e2d2f689a1b 100644 --- a/gms/src/main/resources/sql/init.sql +++ b/gms/src/main/resources/sql/init.sql @@ -8,7 +8,7 @@ CREATE TABLE gms_group ( ); CREATE INDEX group_path_gist_idx ON gms_group USING GIST(path); -CREATE INDEX group_path_idx ON gms_group USING btree(path); +CREATE UNIQUE INDEX group_path_idx ON gms_group USING btree(path); CREATE INDEX group_name_idx ON gms_group USING btree(name); CREATE TABLE gms_membership ( @@ -24,6 +24,8 @@ CREATE TABLE gms_permission ( group_id varchar NOT NULL, user_id varchar NOT NULL, permission permission_type NOT NULL, + group_path ltree NOT NULL, -- group_path is copied here for performance reasons primary key (group_id, user_id, permission), - foreign key (group_id) references gms_group(id) + foreign key (group_id) references gms_group(id), + foreign key (group_path) references gms_group(path) ); diff --git a/gms/src/test/java/it/inaf/ia2/gms/controller/GroupsControllerTest.java b/gms/src/test/java/it/inaf/ia2/gms/controller/GroupsControllerTest.java index fc12cfc31f0fc9fd2fe6cfec51903af3bc77d2e9..8a1ac938dfc95076607203e63b6dc212725e1a82 100644 --- a/gms/src/test/java/it/inaf/ia2/gms/controller/GroupsControllerTest.java +++ b/gms/src/test/java/it/inaf/ia2/gms/controller/GroupsControllerTest.java @@ -3,7 +3,7 @@ package it.inaf.ia2.gms.controller; import it.inaf.ia2.gms.authn.SessionData; import it.inaf.ia2.gms.model.GroupsModelRequest; import it.inaf.ia2.gms.model.GroupsModelResponse; -import it.inaf.ia2.gms.service.GroupsModelService; +import it.inaf.ia2.gms.service.GroupsModelBuilder; import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Test; @@ -28,7 +28,7 @@ public class GroupsControllerTest { private SessionData session; @Mock - private GroupsModelService groupsModelService; + private GroupsModelBuilder groupsModelService; @InjectMocks private GroupsController controller; diff --git a/gms/src/test/java/it/inaf/ia2/gms/persistence/GroupEntityTest.java b/gms/src/test/java/it/inaf/ia2/gms/persistence/GroupEntityTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6e71cef1a8aabf8c5833d546c4b74db34d69618c --- /dev/null +++ b/gms/src/test/java/it/inaf/ia2/gms/persistence/GroupEntityTest.java @@ -0,0 +1,28 @@ +package it.inaf.ia2.gms.persistence; + +import it.inaf.ia2.gms.persistence.model.GroupEntity; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class GroupEntityTest { + + @Test + public void testGetParentPath() { + + GroupEntity root = new GroupEntity(); + root.setPath(""); + assertNull(root.getParentPath()); + + GroupEntity lbt = new GroupEntity(); + lbt.setPath("LBT"); + assertEquals("", lbt.getParentPath()); + + GroupEntity p1 = new GroupEntity(); + p1.setPath("LBT.INAF.P1"); + assertEquals("LBT.INAF", p1.getParentPath()); + } +} diff --git a/gms/src/test/java/it/inaf/ia2/gms/persistence/GroupsDAOTest.java b/gms/src/test/java/it/inaf/ia2/gms/persistence/GroupsDAOTest.java index 530947872eb2de94989066e248650c868261afb2..643cef67672d291bb775580a44ad96002150de5c 100644 --- a/gms/src/test/java/it/inaf/ia2/gms/persistence/GroupsDAOTest.java +++ b/gms/src/test/java/it/inaf/ia2/gms/persistence/GroupsDAOTest.java @@ -2,9 +2,11 @@ package it.inaf.ia2.gms.persistence; import com.google.common.collect.ImmutableSet; import io.zonky.test.db.AutoConfigureEmbeddedDatabase; -import it.inaf.ia2.gms.persistence.model.NewGroup; +import it.inaf.ia2.gms.model.GroupBreadcrumb; +import it.inaf.ia2.gms.persistence.model.GroupEntity; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.UUID; import javax.sql.DataSource; import static org.junit.Assert.assertEquals; @@ -36,32 +38,48 @@ public class GroupsDAOTest { public void testAll() { // Create groups - NewGroup root = new NewGroup(); + GroupEntity root = new GroupEntity(); root.setId("ROOT"); root.setName("ROOT"); root.setPath(""); dao.createGroup(root); - NewGroup lbt = new NewGroup(); + GroupEntity lbt = new GroupEntity(); lbt.setId(getNewGroupId()); lbt.setName("LBT"); lbt.setPath(lbt.getId()); dao.createGroup(lbt); - NewGroup tng = new NewGroup(); + GroupEntity tng = new GroupEntity(); tng.setId(getNewGroupId()); tng.setName("TNG"); tng.setPath(tng.getId()); dao.createGroup(tng); - NewGroup lbtInaf = new NewGroup(); + GroupEntity lbtInaf = new GroupEntity(); lbtInaf.setId(getNewGroupId()); lbtInaf.setName("INAF"); lbtInaf.setPath(lbt.getId() + "." + lbtInaf.getId()); dao.createGroup(lbtInaf); + // Check count + assertEquals(4, dao.count()); + + // Find by id + Optional<GroupEntity> group = dao.findGroupById(lbtInaf.getId()); + assertTrue(group.isPresent()); + assertEquals(lbtInaf, group.get()); + + group = dao.findGroupByPath(lbtInaf.getPath()); + assertTrue(group.isPresent()); + assertEquals(lbtInaf, group.get()); + + // Find unexisting group + group = dao.findGroupById("not-found"); + assertFalse(group.isPresent()); + // Sub list - List<NewGroup> groups = dao.listSubGroups(""); + List<GroupEntity> groups = dao.listSubGroups(""); assertEquals(2, groups.size()); assertEquals("LBT", groups.get(0).getName()); assertEquals("TNG", groups.get(1).getName()); @@ -69,17 +87,31 @@ public class GroupsDAOTest { groups = dao.listSubGroups(lbt.getId()); assertEquals(1, groups.size()); assertEquals("INAF", groups.get(0).getName()); - + // Children map Map<String, Boolean> childrenMap = dao.getHasChildrenMap(ImmutableSet.of(root.getId())); assertEquals(1, childrenMap.size()); assertTrue(childrenMap.get(root.getId())); - + childrenMap = dao.getHasChildrenMap(ImmutableSet.of(lbt.getId(), tng.getId())); assertEquals(2, childrenMap.size()); assertTrue(childrenMap.get(lbt.getId())); assertFalse(childrenMap.get(tng.getId())); + // Rename + String newName = "renamed"; + tng.setName(newName); + dao.updateGroup(tng); + tng = dao.findGroupById(tng.getId()).get(); + assertEquals(newName, tng.getName()); + + // Breadcrumbs + List<GroupBreadcrumb> breadcrumbs = dao.getBreadcrumbs(lbt.getId() + "." + lbtInaf.getId()); + assertEquals(3, breadcrumbs.size()); + assertEquals(root.getName(), breadcrumbs.get(0).getGroupName()); + assertEquals(lbt.getName(), breadcrumbs.get(1).getGroupName()); + assertEquals(lbtInaf.getName(), breadcrumbs.get(2).getGroupName()); + // Delete dao.deleteGroupById(lbtInaf.getId()); groups = dao.listSubGroups(lbt.getId()); diff --git a/gms/src/test/java/it/inaf/ia2/gms/persistence/NestedGroupsIntegrationTest.java b/gms/src/test/java/it/inaf/ia2/gms/persistence/NestedGroupsIntegrationTest.java index fdf493db76e00c089a0d9d755ce3f1885a594d2a..2c546b004db478db6d0e2fbfa3b689e43c106838 100644 --- a/gms/src/test/java/it/inaf/ia2/gms/persistence/NestedGroupsIntegrationTest.java +++ b/gms/src/test/java/it/inaf/ia2/gms/persistence/NestedGroupsIntegrationTest.java @@ -1,12 +1,13 @@ package it.inaf.ia2.gms.persistence; -import it.inaf.ia2.gms.persistence.model.Group; -import it.inaf.ia2.gms.persistence.model.Membership; -import it.inaf.ia2.gms.persistence.model.User; -import it.inaf.ia2.gms.persistence.model.UserGroupPermission; +import io.zonky.test.db.AutoConfigureEmbeddedDatabase; import it.inaf.ia2.gms.service.GroupsService; import it.inaf.ia2.gms.model.GroupNode; +import it.inaf.ia2.gms.model.PaginatedModelRequest; import it.inaf.ia2.gms.model.Permission; +import it.inaf.ia2.gms.persistence.model.GroupEntity; +import it.inaf.ia2.gms.persistence.model.PermissionEntity; +import it.inaf.ia2.gms.service.GroupsTreeBuilder; import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -14,144 +15,129 @@ import static org.junit.Assert.assertTrue; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.test.context.junit4.SpringRunner; -@DataJpaTest -@AutoConfigureTestDatabase @RunWith(SpringRunner.class) +@AutoConfigureEmbeddedDatabase(beanName = "dataSource") public class NestedGroupsIntegrationTest { @Autowired - private UsersRepository usersRepository; + private PermissionsDAO permissionsDAO; @Autowired - private GroupsRepository groupsRepository; + private GroupsService groupsService; @Autowired - private PermissionsRepository permissionsRepository; - - @Autowired - private MembershipRepository membershipRepository; + private GroupsTreeBuilder groupsTreeBuilder; @Test public void testNestedGroupRetrieval() { - GroupsService groupsService = new GroupsService(groupsRepository, - permissionsRepository, membershipRepository); - - // Create user - User user = new User(); - user.setId("user"); - user = usersRepository.save(user); + String userId = "USER_ID"; // Test super admin - UserGroupPermission superAdminPermission = new UserGroupPermission(); - superAdminPermission.setUser(user); - superAdminPermission.setGroup(groupsRepository.findById(GroupsService.ROOT).get()); + PermissionEntity superAdminPermission = new PermissionEntity(); + superAdminPermission.setUserId(userId); + superAdminPermission.setGroupId(GroupsService.ROOT); superAdminPermission.setPermission(Permission.ADMIN); - permissionsRepository.save(superAdminPermission); + superAdminPermission.setGroupPath(""); + permissionsDAO.createPermission(superAdminPermission); // Setup groups - Group root = groupsService.getGroupById(GroupsService.ROOT); - Group lbt = groupsService.addGroup(GroupsService.ROOT, "LBT", user); - Group tng = groupsService.addGroup(GroupsService.ROOT, "TNG", user); - Group radio = groupsService.addGroup(GroupsService.ROOT, "Radio", user); - Group lbtInaf = groupsService.addGroup(lbt.getId(), "INAF", user); - Group lbtInafProgram1 = groupsService.addGroup(lbtInaf.getId(), "P1", user); - Group lbtInafProgram2 = groupsService.addGroup(lbtInaf.getId(), "P2", user); + GroupEntity root = groupsService.getGroupById(GroupsService.ROOT); + GroupEntity lbt = groupsService.addGroup(GroupsService.ROOT, "LBT", userId); + GroupEntity tng = groupsService.addGroup(GroupsService.ROOT, "TNG", userId); + GroupEntity radio = groupsService.addGroup(GroupsService.ROOT, "Radio", userId); + GroupEntity lbtInaf = groupsService.addGroup(lbt.getId(), "INAF", userId); + GroupEntity lbtInafProgram1 = groupsService.addGroup(lbtInaf.getId(), "P1", userId); + GroupEntity lbtInafProgram2 = groupsService.addGroup(lbtInaf.getId(), "P2", userId); + + PaginatedModelRequest request = new PaginatedModelRequest(); + request.setPaginatorPage(1); + request.setPaginatorPageSize(50); // Test super admin - level 0 (ROOT) - List<GroupNode> groupNodes = groupNodes = groupsService.getSubgroups(root, user); + List<GroupNode> groupNodes = groupNodes = groupsTreeBuilder.listSubGroups(root.getId(), userId, request).getItems(); assertEquals(3, groupNodes.size()); GroupNode lbtGN = groupNodes.get(0); assertEquals("LBT", lbtGN.getGroupName()); - assertEquals(1, lbtGN.getPermissions().size()); - assertEquals(Permission.ADMIN, lbtGN.getPermissions().get(0)); + assertEquals(Permission.ADMIN, lbtGN.getPermission()); assertTrue(lbtGN.isHasChildren()); GroupNode radioGN = groupNodes.get(1); assertEquals("Radio", radioGN.getGroupName()); - assertEquals(Permission.ADMIN, radioGN.getPermissions().get(0)); + assertEquals(Permission.ADMIN, radioGN.getPermission()); assertFalse(radioGN.isHasChildren()); GroupNode tngGN = groupNodes.get(2); assertEquals("TNG", tngGN.getGroupName()); - assertEquals(Permission.ADMIN, tngGN.getPermissions().get(0)); + assertEquals(Permission.ADMIN, tngGN.getPermission()); assertFalse(tngGN.isHasChildren()); // Test super admin - level 1 - groupNodes = groupsService.getSubgroups(lbt, user); + groupNodes = groupsTreeBuilder.listSubGroups(lbt.getId(), userId, request).getItems(); assertEquals(1, groupNodes.size()); GroupNode INAFGN = groupNodes.get(0); assertEquals("INAF", INAFGN.getGroupName()); - assertEquals(Permission.ADMIN, INAFGN.getPermissions().get(0)); + assertEquals(Permission.ADMIN, INAFGN.getPermission()); assertTrue(INAFGN.isHasChildren()); // Test super admin - level 2 - groupNodes = groupsService.getSubgroups(lbtInaf, user); + groupNodes = groupsTreeBuilder.listSubGroups(lbtInaf.getId(), userId, request).getItems(); assertEquals(2, groupNodes.size()); GroupNode p1 = groupNodes.get(0); assertEquals("P1", p1.getGroupName()); - assertEquals(1, p1.getPermissions().size()); - assertEquals(Permission.ADMIN, p1.getPermissions().get(0)); + assertEquals(Permission.ADMIN, p1.getPermission()); assertFalse(p1.isHasChildren()); GroupNode p2 = groupNodes.get(1); assertEquals("P2", p2.getGroupName()); - assertEquals(Permission.ADMIN, p2.getPermissions().get(0)); + assertEquals(Permission.ADMIN, p2.getPermission()); assertFalse(p2.isHasChildren()); // Setup lower permissions - permissionsRepository.delete(superAdminPermission); + permissionsDAO.deletePermission(superAdminPermission.getGroupId(), + superAdminPermission.getUserId(), superAdminPermission.getPermission()); - UserGroupPermission p1Permission = new UserGroupPermission(); - p1Permission.setUser(user); - p1Permission.setGroup(lbtInafProgram1); + PermissionEntity p1Permission = new PermissionEntity(); + p1Permission.setUserId(userId); + p1Permission.setGroupId(lbtInafProgram1.getId()); p1Permission.setPermission(Permission.MANAGE_MEMBERS); - permissionsRepository.save(p1Permission); + permissionsDAO.createPermission(p1Permission); - UserGroupPermission lbtPermission = new UserGroupPermission(); - lbtPermission.setUser(user); - lbtPermission.setGroup(lbtInaf); + PermissionEntity lbtPermission = new PermissionEntity(); + lbtPermission.setUserId(userId); + lbtPermission.setGroupId(lbtInaf.getId()); lbtPermission.setPermission(Permission.VIEW_MEMBERS); - permissionsRepository.save(lbtPermission); - - // Setup membership - Membership membership = new Membership(); - membership.setUser(user); - membership.setGroup(radio); - membershipRepository.save(membership); + permissionsDAO.createPermission(lbtPermission); // Check level 0 (ROOT) - groupNodes = groupsService.getSubgroups(root, user); + groupNodes = groupsTreeBuilder.listSubGroups(root.getId(), userId, request).getItems(); assertEquals(2, groupNodes.size()); lbtGN = groupNodes.get(0); assertEquals("LBT", lbtGN.getGroupName()); - assertEquals(Permission.TRAVERSE, lbtGN.getPermissions().get(0)); + assertEquals(Permission.TRAVERSE, lbtGN.getPermission()); assertTrue(lbtGN.isHasChildren()); radioGN = groupNodes.get(1); assertEquals("Radio", radioGN.getGroupName()); - assertEquals(Permission.TRAVERSE, radioGN.getPermissions().get(0)); + assertEquals(Permission.TRAVERSE, radioGN.getPermission()); assertFalse(radioGN.isHasChildren()); // Check level 1 - groupNodes = groupsService.getSubgroups(lbt, user); + groupNodes = groupsTreeBuilder.listSubGroups(lbt.getId(), userId, request).getItems(); assertEquals(1, groupNodes.size()); INAFGN = groupNodes.get(0); assertEquals("INAF", INAFGN.getGroupName()); - assertEquals(Permission.VIEW_MEMBERS, INAFGN.getPermissions().get(0)); + assertEquals(Permission.VIEW_MEMBERS, INAFGN.getPermission()); assertTrue(INAFGN.isHasChildren()); // Check level 2 - groupNodes = groupsService.getSubgroups(lbtInaf, user); + groupNodes = groupsTreeBuilder.listSubGroups(lbtInaf.getId(), userId, request).getItems(); assertEquals(2, groupNodes.size()); p1 = groupNodes.get(0); assertEquals("P1", p1.getGroupName()); - assertEquals(1, p1.getPermissions().size()); - assertEquals(Permission.MANAGE_MEMBERS, p1.getPermissions().get(0)); + assertEquals(Permission.MANAGE_MEMBERS, p1.getPermission()); assertFalse(p1.isHasChildren()); p2 = groupNodes.get(1); assertEquals("P2", p2.getGroupName()); - assertEquals(Permission.VIEW_MEMBERS, p2.getPermissions().get(0)); + assertEquals(Permission.VIEW_MEMBERS, p2.getPermission()); assertFalse(p2.isHasChildren()); } } diff --git a/gms/src/test/java/it/inaf/ia2/gms/persistence/PermissionsDAOTest.java b/gms/src/test/java/it/inaf/ia2/gms/persistence/PermissionsDAOTest.java index b5c9a8ef76e7c7f5c68653f5bf96807b00f9f298..e2bb67d9b5e05570efd0e58de4f92514abd969e7 100644 --- a/gms/src/test/java/it/inaf/ia2/gms/persistence/PermissionsDAOTest.java +++ b/gms/src/test/java/it/inaf/ia2/gms/persistence/PermissionsDAOTest.java @@ -2,8 +2,8 @@ package it.inaf.ia2.gms.persistence; import io.zonky.test.db.AutoConfigureEmbeddedDatabase; import it.inaf.ia2.gms.model.Permission; -import it.inaf.ia2.gms.persistence.model.UserPermission; -import it.inaf.ia2.gms.persistence.model.NewGroup; +import it.inaf.ia2.gms.persistence.model.PermissionEntity; +import it.inaf.ia2.gms.persistence.model.GroupEntity; import java.util.List; import javax.sql.DataSource; import static org.junit.Assert.assertEquals; @@ -35,7 +35,7 @@ public class PermissionsDAOTest { @Sql("/sql/init.sql") public void testAll() { - NewGroup root = new NewGroup(); + GroupEntity root = new GroupEntity(); root.setId("ROOT"); root.setName("ROOT"); root.setPath(""); @@ -43,20 +43,27 @@ public class PermissionsDAOTest { String userId = "user_id"; - UserPermission permission = new UserPermission(); + PermissionEntity permission = new PermissionEntity(); permission.setGroupId(root.getId()); permission.setUserId(userId); permission.setPermission(Permission.ADMIN); + permission.setGroupPath(root.getPath()); permissionsDAO.createPermission(permission); - List<UserPermission> permissions = permissionsDAO.findUserPermissions(userId); + List<PermissionEntity> permissions = permissionsDAO.findUserPermissions(userId); assertEquals(1, permissions.size()); assertEquals(Permission.ADMIN, permissions.get(0).getPermission()); assertEquals(userId, permissions.get(0).getUserId()); - permissionsDAO.deletePermission(permission); + permissions = permissionsDAO.findUserPermissions(userId, root.getPath()); + assertEquals(1, permissions.size()); + + permissions = permissionsDAO.getGroupsPermissions(root.getId()); + assertEquals(1, permissions.size()); + + permissionsDAO.deletePermission(permission.getGroupId(), permission.getUserId(), permission.getPermission()); permissions = permissionsDAO.findUserPermissions(userId); assertTrue(permissions.isEmpty()); 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 99e6479a10502010aec98ee3b26e2f092b7bd750..1273d72a251d656eaa5ede726b297a1fa39d32a4 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 @@ -1,14 +1,13 @@ package it.inaf.ia2.gms.service; +import io.zonky.test.db.AutoConfigureEmbeddedDatabase; import it.inaf.ia2.gms.model.Permission; import it.inaf.ia2.gms.model.RapUser; import it.inaf.ia2.gms.model.UserPermission; -import it.inaf.ia2.gms.persistence.GroupsRepository; -import it.inaf.ia2.gms.persistence.PermissionsRepository; -import it.inaf.ia2.gms.persistence.UsersRepository; -import it.inaf.ia2.gms.persistence.model.Group; -import it.inaf.ia2.gms.persistence.model.User; -import it.inaf.ia2.gms.persistence.model.UserGroupPermission; +import it.inaf.ia2.gms.persistence.GroupsDAO; +import it.inaf.ia2.gms.persistence.PermissionsDAO; +import it.inaf.ia2.gms.persistence.model.GroupEntity; +import it.inaf.ia2.gms.persistence.model.PermissionEntity; import it.inaf.ia2.gms.rap.RapClient; import java.util.Collections; import java.util.List; @@ -18,26 +17,20 @@ import org.junit.runner.RunWith; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit4.SpringRunner; -@DataJpaTest -@AutoConfigureTestDatabase @RunWith(SpringRunner.class) +@AutoConfigureEmbeddedDatabase(beanName = "dataSource") public class PermissionsServiceIntegrationTest { private static final String USER_ID = "USER_ID"; @Autowired - private UsersRepository usersRepository; + private GroupsDAO groupsDAO; @Autowired - private GroupsRepository groupsRepository; - - @Autowired - private PermissionsRepository permissionsRepository; + private PermissionsDAO permissionsDAO; @MockBean private RapClient rapClient; @@ -50,23 +43,21 @@ public class PermissionsServiceIntegrationTest { rapUser.setId(USER_ID); when(rapClient.getUsers(any())).thenReturn(Collections.singletonList(rapUser)); - PermissionsService permissionsService = new PermissionsService(permissionsRepository, rapClient); - - // Create user - User user = new User(); - user.setId(USER_ID); - user = usersRepository.save(user); + PermissionsService permissionsService = new PermissionsService(permissionsDAO, rapClient); - Group root = new Group(); + // Create root + GroupEntity root = new GroupEntity(); root.setId(GroupsService.ROOT); root.setName(GroupsService.ROOT); - root = groupsRepository.save(root); + root.setPath(""); + root = groupsDAO.createGroup(root); - UserGroupPermission superAdminPermission = new UserGroupPermission(); - superAdminPermission.setUser(user); - superAdminPermission.setGroup(root); + PermissionEntity superAdminPermission = new PermissionEntity(); + superAdminPermission.setUserId(USER_ID); + superAdminPermission.setGroupId(root.getId()); superAdminPermission.setPermission(Permission.ADMIN); - permissionsRepository.save(superAdminPermission); + superAdminPermission.setGroupPath(root.getPath()); + permissionsDAO.createPermission(superAdminPermission); List<UserPermission> permissions = permissionsService.getUserPermissions(root);