Loading src/main/java/it/inaf/oats/vospace/CollectionsController.java +51 −0 Original line number Original line Diff line number Diff line Loading @@ -8,6 +8,7 @@ package it.inaf.oats.vospace; import it.inaf.ia2.aa.data.User; import it.inaf.ia2.aa.data.User; import it.inaf.oats.vospace.datamodel.collections.NodeCollection; import it.inaf.oats.vospace.datamodel.collections.NodeCollection; import it.inaf.oats.vospace.datamodel.collections.NodeCollectionsWrapper; import it.inaf.oats.vospace.datamodel.collections.NodeCollectionsWrapper; import it.inaf.oats.vospace.datamodel.collections.NodeDetailsWrapper; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory; Loading @@ -18,6 +19,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController; /** /** Loading Loading @@ -73,4 +75,53 @@ public class CollectionsController { } } // add node to collection @PutMapping(value = "/addnode/{collectionId}") public ResponseEntity<String> addNodeToCollection( @PathVariable("collectionId") Long collectionId, @RequestParam("vosPath") String vosPath, User principal) { LOG.debug("add node {} to collection {} called for user {}", vosPath, collectionId, principal.getName() ); collectionsService.addNodeToCollection(vosPath, collectionId, principal.getName(), principal.getGroups()); return ResponseEntity.ok("Node added"); } // add node to collection @DeleteMapping(value = "/removenode/{collectionId}") public ResponseEntity<String> removeNodeFromCollection( @PathVariable("collectionId") Long collectionId, @RequestParam("vosPath") String vosPath, User principal) { LOG.debug("remove node {} from collection {} called for user {}", vosPath, collectionId, principal.getName() ); collectionsService.removeNodeFromCollection(vosPath, collectionId, principal.getName(), principal.getGroups()); return ResponseEntity.ok("Node added"); } @GetMapping(value = "/getnodesincollection/{collectionId}") public ResponseEntity<NodeDetailsWrapper> getNodesInCollection( @PathVariable("collectionId") Long collectionId, User principal) { LOG.debug("get nodes in collection {} called for user {}", collectionId, principal.getName()); NodeDetailsWrapper ndw = new NodeDetailsWrapper(); ndw.setNodeDetails( collectionsService.getNodeDetailsInCollection( collectionId, principal.getName())); return ResponseEntity.ok(ndw); } } } src/main/java/it/inaf/oats/vospace/CollectionsService.java +114 −21 Original line number Original line Diff line number Diff line Loading @@ -7,12 +7,21 @@ package it.inaf.oats.vospace; import it.inaf.oats.vospace.persistence.CollectionsDAO; import it.inaf.oats.vospace.persistence.CollectionsDAO; import it.inaf.oats.vospace.datamodel.collections.NodeCollection; import it.inaf.oats.vospace.datamodel.collections.NodeCollection; import it.inaf.oats.vospace.datamodel.collections.NodeDetails; import it.inaf.oats.vospace.exception.InvalidArgumentException; import it.inaf.oats.vospace.exception.NodeBusyException; import it.inaf.oats.vospace.exception.PermissionDeniedException; import it.inaf.oats.vospace.exception.PermissionDeniedException; import it.inaf.oats.vospace.exception.NodeNotFoundException; import it.inaf.oats.vospace.persistence.NodeDAO; import it.inaf.oats.vospace.persistence.NodeDAO.ShortNodeDescriptor; import java.util.ArrayList; import java.util.ArrayList; import java.util.List; import java.util.List; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** /** * * Loading @@ -25,37 +34,122 @@ public class CollectionsService { @Autowired @Autowired private CollectionsDAO collectionsDAO; private CollectionsDAO collectionsDAO; @Autowired private NodeDAO nodeDAO; public List<NodeCollection> listCollections(String userId) { public List<NodeCollection> listCollections(String userId) { List<NodeCollection> result = new ArrayList<>(); this.doCheckUserAuth(userId); // If user is not authenticated simply return an empty list List<NodeCollection> result = new ArrayList<>(); if (isUserAuthenticated(userId)) { result.addAll(collectionsDAO.getUserNodeCollections(userId)); result.addAll( collectionsDAO.getUserNodeCollections(userId)); } else { throw new PermissionDeniedException("Authentication required"); } return result; return result; } } public void createNewCollection(String collectionTitle, String userId) { public void createNewCollection(String collectionTitle, String userId) { if (isUserAuthenticated(userId)) { this.doCheckUserAuth(userId); collectionsDAO.createNewCollection(collectionTitle, userId); collectionsDAO.createNewCollection(collectionTitle, userId); } else { throw new PermissionDeniedException("Authentication required"); } } } public void deleteCollectionById(Long collectionId, String userId) { public void deleteCollectionById(Long collectionId, String userId) { if(isUserAuthenticated(userId)) this.doCheckUserAuth(userId); { collectionsDAO.deleteCollection(collectionId, userId); if (collectionsDAO.deleteCollection(collectionId, userId) != 1) { // TODO: throw exceptions if collection not found or deletion requested throw new InvalidArgumentException("Collection not found"); // by someone who is not the owner } } else { } @Transactional(rollbackFor = {Exception.class}, isolation = Isolation.REPEATABLE_READ) public List<NodeDetails> getNodeDetailsInCollection(Long collectionId, String userId) { this.doCheckUserAuth(userId); Optional<NodeCollection> maybeNc = collectionsDAO.getNodeCollectionById(collectionId); NodeCollection nc = maybeNc.orElseThrow( () -> { return new InvalidArgumentException("Collection not found"); }); if (!nc.getOwnerId().equals(userId)) { throw new PermissionDeniedException("User doesn't own collection"); } return collectionsDAO.getNodeDetailsInCollection(nc.getId()); } @Transactional(rollbackFor = {Exception.class}, isolation = Isolation.REPEATABLE_READ) public void addNodeToCollection(String vosPath, Long collectionId, String userId, List<String> userGroups) { this.doCheckUserAuth(userId); this.checkCollectionForOperations(collectionId, userId); Long nodeId = this.checkNodeForOperations(vosPath, userId, userGroups); collectionsDAO.addNodeToCollection(nodeId, collectionId); } @Transactional(rollbackFor = {Exception.class}, isolation = Isolation.REPEATABLE_READ) public void removeNodeFromCollection(String vosPath, Long collectionId, String userId, List<String> userGroups) { this.doCheckUserAuth(userId); this.checkCollectionForOperations(collectionId, userId); Long nodeId = checkNodeForOperations(vosPath, userId, userGroups); if (collectionsDAO .removeNodeFromCollection(nodeId, collectionId) != 1) { throw new InvalidArgumentException("Node is not in collection"); } } private void checkCollectionForOperations(Long collectionId, String userId) { Optional<NodeCollection> maybeNc = collectionsDAO.getNodeCollectionById(collectionId); NodeCollection nc = maybeNc .orElseThrow(() -> { return new InvalidArgumentException("collection doesn't exist"); }); if (!nc.getOwnerId().equals(userId)) { throw new PermissionDeniedException("User doesn't own collection"); } } private Long checkNodeForOperations(String vosPath, String userId, List<String> userGroups) { Optional<ShortNodeDescriptor> maybeSnd = nodeDAO.getShortNodeDescriptor(vosPath, userId, userGroups); ShortNodeDescriptor snd = maybeSnd .orElseThrow(() -> { return new NodeNotFoundException(vosPath); }); // check if node is owned by the user and not busy if (!snd.getCreatorId().equals(userId)) { throw new PermissionDeniedException( "User doesn't own node"); } if (snd.isBusy()) { throw new NodeBusyException(vosPath); } return snd.getNodeId(); } private void doCheckUserAuth(String userId) { if (!isUserAuthenticated(userId)) { throw new PermissionDeniedException("Authentication required"); throw new PermissionDeniedException("Authentication required"); } } } } Loading @@ -64,5 +158,4 @@ public class CollectionsService { return userId != null return userId != null && !userId.equals("anonymous"); && !userId.equals("anonymous"); } } } } src/main/java/it/inaf/oats/vospace/persistence/CollectionsDAO.java +32 −11 Original line number Original line Diff line number Diff line Loading @@ -6,6 +6,7 @@ package it.inaf.oats.vospace.persistence; package it.inaf.oats.vospace.persistence; import it.inaf.oats.vospace.datamodel.collections.NodeCollection; import it.inaf.oats.vospace.datamodel.collections.NodeCollection; import it.inaf.oats.vospace.datamodel.collections.NodeDetails; import java.sql.PreparedStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLException; Loading Loading @@ -66,6 +67,32 @@ public class CollectionsDAO { } } public List<NodeDetails> getNodeDetailsInCollection(Long collectionId) { String sql = "SELECT node_id, get_vos_path(node_id) as node_vos_path\n" + "FROM collections_node WHERE collection_id = ?"; return jdbcTemplate.query( conn-> { PreparedStatement ps = conn.prepareStatement(sql); ps.setLong(1, collectionId); return ps; }, (row, index) -> { return this.getNodeDetailsFromResultset(row); }); } private NodeDetails getNodeDetailsFromResultset(ResultSet rs) throws SQLException { NodeDetails nd = new NodeDetails(); nd.setNodeId(rs.getLong("node_id")); nd.setNodeVosPath(rs.getString("node_vos_path")); return nd; } public List<NodeCollection> getUserNodeCollections(String userId) { public List<NodeCollection> getUserNodeCollections(String userId) { String sql = "SELECT collection_id, title, owner_id FROM collections\n" String sql = "SELECT collection_id, title, owner_id FROM collections\n" + "WHERE owner_id = ?"; + "WHERE owner_id = ?"; Loading Loading @@ -96,23 +123,17 @@ public class CollectionsDAO { }); }); } } public void removeNodeFromCollection(Long nodeId, Long collectionId) { public int removeNodeFromCollection(Long nodeId, Long collectionId) { String sql = "DELETE FROM collections_node WHERE collection_id = ? and node_id = ?"; String sql = "DELETE FROM collections_node WHERE collection_id = ? and node_id = ?"; jdbcTemplate.update(sql, collectionId, nodeId); // Returns the number of deleted nodes: must be 1 } return jdbcTemplate.update(sql, collectionId, nodeId); // TODO complete stub public List<NodeCollection> getCollectionsOfNode(Long nodeId) { throw new UnsupportedOperationException(); } } // TODO complete stub: add list of nodes in collection (path list?) public int deleteCollection(Long collectionId, String userId) { public void deleteCollection(Long collectionId, String userId) { String sql = "DELETE FROM collections WHERE collection_id = ? AND owner_id = ?"; String sql = "DELETE FROM collections WHERE collection_id = ? AND owner_id = ?"; jdbcTemplate.update(sql, collectionId, userId); return jdbcTemplate.update(sql, collectionId, userId); } } private NodeCollection getNodeCollectionFromResultset(ResultSet rs) private NodeCollection getNodeCollectionFromResultset(ResultSet rs) Loading src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java +38 −2 Original line number Original line Diff line number Diff line Loading @@ -246,11 +246,14 @@ public class NodeDAO { String userId, List<String> userGroups) { String userId, List<String> userGroups) { String sql = "SELECT path,\n" String sql = "SELECT path,\n" + "n.node_id AS node_id\n" + "n.creator_id as creator_id\n" + "NOT (n.async_trans OR COALESCE(location_type = 'async', FALSE)) AS is_writable,\n" + "NOT (n.async_trans OR COALESCE(location_type = 'async', FALSE)) AS is_writable,\n" + "n.sticky AS is_sticky,\n" + "n.sticky AS is_sticky,\n" + "((SELECT COUNT(*) FROM (SELECT UNNEST(?) INTERSECT SELECT UNNEST(n.group_write)) AS allowed_groups ) = 0 AND\n" + "((SELECT COUNT(*) FROM (SELECT UNNEST(?) INTERSECT SELECT UNNEST(n.group_write)) AS allowed_groups ) = 0 AND\n" + "n.creator_id <> ?) AS is_permission_denied,\n" + "n.creator_id <> ?) AS is_permission_denied,\n" + "n.type = 'container' AS is_container,\n" + "n.type = 'container' AS is_container,\n" + "n.type = 'link' AS is_link,\n" + "n.job_id IS NOT NULL AS busy_state,\n" + "n.job_id IS NOT NULL AS busy_state,\n" + "n.immutable AS is_immutable\n" + "n.immutable AS is_immutable\n" + "FROM node n \n" + "FROM node n \n" Loading @@ -277,14 +280,20 @@ public class NodeDAO { } } String nodePath = rs.getString("path"); String nodePath = rs.getString("path"); Long nodeId = rs.getLong("node_id"); String creatorId = rs.getString(("creator_id")); Boolean isContainer = rs.getBoolean(("is_container")); Boolean isContainer = rs.getBoolean(("is_container")); Boolean isLink = rs.getBoolean(("is_link")); Boolean isWritable = rs.getBoolean("is_writable"); Boolean isWritable = rs.getBoolean("is_writable"); Boolean isBusy = rs.getBoolean("busy_state"); Boolean isBusy = rs.getBoolean("busy_state"); Boolean isPermissionDenied = rs.getBoolean("is_permission_denied"); Boolean isPermissionDenied = rs.getBoolean("is_permission_denied"); Boolean isSticky = rs.getBoolean("is_sticky"); Boolean isSticky = rs.getBoolean("is_sticky"); Boolean isImmutable = rs.getBoolean("is_immutable"); Boolean isImmutable = rs.getBoolean("is_immutable"); ShortNodeDescriptor result = new ShortNodeDescriptor(nodePath, isContainer, isWritable, isBusy, isPermissionDenied, isSticky, isImmutable); ShortNodeDescriptor result = new ShortNodeDescriptor(nodePath, nodeId, creatorId, isContainer, isLink, isWritable, isBusy, isPermissionDenied, isSticky, isImmutable); return Optional.of(result); return Optional.of(result); }); }); Loading Loading @@ -757,17 +766,32 @@ public class NodeDAO { public class ShortNodeDescriptor { public class ShortNodeDescriptor { private final String nodeLtreePath; private final String nodeLtreePath; private final Long nodeId; private final String creatorId; private final boolean container; private final boolean container; private final boolean link; private final boolean writable; private final boolean writable; private final boolean busy; private final boolean busy; private final boolean permissionDenied; private final boolean permissionDenied; private final boolean sticky; private final boolean sticky; private final boolean immutable; private final boolean immutable; public ShortNodeDescriptor(String nodeLtreePath, boolean container, boolean writable, boolean busy, boolean permissionDenied, boolean sticky, boolean immutable) { public ShortNodeDescriptor( String nodeLtreePath, Long nodeId, String creatorId, boolean container, boolean link, boolean writable, boolean busy, boolean permissionDenied, boolean sticky, boolean immutable) { this.nodeLtreePath = nodeLtreePath; this.nodeLtreePath = nodeLtreePath; this.nodeId = nodeId; this.creatorId = creatorId; this.container = container; this.container = container; this.link = link; this.writable = writable; this.writable = writable; this.busy = busy; this.busy = busy; this.permissionDenied = permissionDenied; this.permissionDenied = permissionDenied; Loading @@ -779,10 +803,22 @@ public class NodeDAO { return nodeLtreePath; return nodeLtreePath; } } public Long getNodeId() { return this.nodeId; } public String getCreatorId() { return creatorId; } public boolean isContainer() { public boolean isContainer() { return container; return container; } } public boolean isLink() { return link; } public boolean isImmutable() { public boolean isImmutable() { return immutable; return immutable; } } Loading Loading
src/main/java/it/inaf/oats/vospace/CollectionsController.java +51 −0 Original line number Original line Diff line number Diff line Loading @@ -8,6 +8,7 @@ package it.inaf.oats.vospace; import it.inaf.ia2.aa.data.User; import it.inaf.ia2.aa.data.User; import it.inaf.oats.vospace.datamodel.collections.NodeCollection; import it.inaf.oats.vospace.datamodel.collections.NodeCollection; import it.inaf.oats.vospace.datamodel.collections.NodeCollectionsWrapper; import it.inaf.oats.vospace.datamodel.collections.NodeCollectionsWrapper; import it.inaf.oats.vospace.datamodel.collections.NodeDetailsWrapper; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory; Loading @@ -18,6 +19,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController; /** /** Loading Loading @@ -73,4 +75,53 @@ public class CollectionsController { } } // add node to collection @PutMapping(value = "/addnode/{collectionId}") public ResponseEntity<String> addNodeToCollection( @PathVariable("collectionId") Long collectionId, @RequestParam("vosPath") String vosPath, User principal) { LOG.debug("add node {} to collection {} called for user {}", vosPath, collectionId, principal.getName() ); collectionsService.addNodeToCollection(vosPath, collectionId, principal.getName(), principal.getGroups()); return ResponseEntity.ok("Node added"); } // add node to collection @DeleteMapping(value = "/removenode/{collectionId}") public ResponseEntity<String> removeNodeFromCollection( @PathVariable("collectionId") Long collectionId, @RequestParam("vosPath") String vosPath, User principal) { LOG.debug("remove node {} from collection {} called for user {}", vosPath, collectionId, principal.getName() ); collectionsService.removeNodeFromCollection(vosPath, collectionId, principal.getName(), principal.getGroups()); return ResponseEntity.ok("Node added"); } @GetMapping(value = "/getnodesincollection/{collectionId}") public ResponseEntity<NodeDetailsWrapper> getNodesInCollection( @PathVariable("collectionId") Long collectionId, User principal) { LOG.debug("get nodes in collection {} called for user {}", collectionId, principal.getName()); NodeDetailsWrapper ndw = new NodeDetailsWrapper(); ndw.setNodeDetails( collectionsService.getNodeDetailsInCollection( collectionId, principal.getName())); return ResponseEntity.ok(ndw); } } }
src/main/java/it/inaf/oats/vospace/CollectionsService.java +114 −21 Original line number Original line Diff line number Diff line Loading @@ -7,12 +7,21 @@ package it.inaf.oats.vospace; import it.inaf.oats.vospace.persistence.CollectionsDAO; import it.inaf.oats.vospace.persistence.CollectionsDAO; import it.inaf.oats.vospace.datamodel.collections.NodeCollection; import it.inaf.oats.vospace.datamodel.collections.NodeCollection; import it.inaf.oats.vospace.datamodel.collections.NodeDetails; import it.inaf.oats.vospace.exception.InvalidArgumentException; import it.inaf.oats.vospace.exception.NodeBusyException; import it.inaf.oats.vospace.exception.PermissionDeniedException; import it.inaf.oats.vospace.exception.PermissionDeniedException; import it.inaf.oats.vospace.exception.NodeNotFoundException; import it.inaf.oats.vospace.persistence.NodeDAO; import it.inaf.oats.vospace.persistence.NodeDAO.ShortNodeDescriptor; import java.util.ArrayList; import java.util.ArrayList; import java.util.List; import java.util.List; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; /** /** * * Loading @@ -25,37 +34,122 @@ public class CollectionsService { @Autowired @Autowired private CollectionsDAO collectionsDAO; private CollectionsDAO collectionsDAO; @Autowired private NodeDAO nodeDAO; public List<NodeCollection> listCollections(String userId) { public List<NodeCollection> listCollections(String userId) { List<NodeCollection> result = new ArrayList<>(); this.doCheckUserAuth(userId); // If user is not authenticated simply return an empty list List<NodeCollection> result = new ArrayList<>(); if (isUserAuthenticated(userId)) { result.addAll(collectionsDAO.getUserNodeCollections(userId)); result.addAll( collectionsDAO.getUserNodeCollections(userId)); } else { throw new PermissionDeniedException("Authentication required"); } return result; return result; } } public void createNewCollection(String collectionTitle, String userId) { public void createNewCollection(String collectionTitle, String userId) { if (isUserAuthenticated(userId)) { this.doCheckUserAuth(userId); collectionsDAO.createNewCollection(collectionTitle, userId); collectionsDAO.createNewCollection(collectionTitle, userId); } else { throw new PermissionDeniedException("Authentication required"); } } } public void deleteCollectionById(Long collectionId, String userId) { public void deleteCollectionById(Long collectionId, String userId) { if(isUserAuthenticated(userId)) this.doCheckUserAuth(userId); { collectionsDAO.deleteCollection(collectionId, userId); if (collectionsDAO.deleteCollection(collectionId, userId) != 1) { // TODO: throw exceptions if collection not found or deletion requested throw new InvalidArgumentException("Collection not found"); // by someone who is not the owner } } else { } @Transactional(rollbackFor = {Exception.class}, isolation = Isolation.REPEATABLE_READ) public List<NodeDetails> getNodeDetailsInCollection(Long collectionId, String userId) { this.doCheckUserAuth(userId); Optional<NodeCollection> maybeNc = collectionsDAO.getNodeCollectionById(collectionId); NodeCollection nc = maybeNc.orElseThrow( () -> { return new InvalidArgumentException("Collection not found"); }); if (!nc.getOwnerId().equals(userId)) { throw new PermissionDeniedException("User doesn't own collection"); } return collectionsDAO.getNodeDetailsInCollection(nc.getId()); } @Transactional(rollbackFor = {Exception.class}, isolation = Isolation.REPEATABLE_READ) public void addNodeToCollection(String vosPath, Long collectionId, String userId, List<String> userGroups) { this.doCheckUserAuth(userId); this.checkCollectionForOperations(collectionId, userId); Long nodeId = this.checkNodeForOperations(vosPath, userId, userGroups); collectionsDAO.addNodeToCollection(nodeId, collectionId); } @Transactional(rollbackFor = {Exception.class}, isolation = Isolation.REPEATABLE_READ) public void removeNodeFromCollection(String vosPath, Long collectionId, String userId, List<String> userGroups) { this.doCheckUserAuth(userId); this.checkCollectionForOperations(collectionId, userId); Long nodeId = checkNodeForOperations(vosPath, userId, userGroups); if (collectionsDAO .removeNodeFromCollection(nodeId, collectionId) != 1) { throw new InvalidArgumentException("Node is not in collection"); } } private void checkCollectionForOperations(Long collectionId, String userId) { Optional<NodeCollection> maybeNc = collectionsDAO.getNodeCollectionById(collectionId); NodeCollection nc = maybeNc .orElseThrow(() -> { return new InvalidArgumentException("collection doesn't exist"); }); if (!nc.getOwnerId().equals(userId)) { throw new PermissionDeniedException("User doesn't own collection"); } } private Long checkNodeForOperations(String vosPath, String userId, List<String> userGroups) { Optional<ShortNodeDescriptor> maybeSnd = nodeDAO.getShortNodeDescriptor(vosPath, userId, userGroups); ShortNodeDescriptor snd = maybeSnd .orElseThrow(() -> { return new NodeNotFoundException(vosPath); }); // check if node is owned by the user and not busy if (!snd.getCreatorId().equals(userId)) { throw new PermissionDeniedException( "User doesn't own node"); } if (snd.isBusy()) { throw new NodeBusyException(vosPath); } return snd.getNodeId(); } private void doCheckUserAuth(String userId) { if (!isUserAuthenticated(userId)) { throw new PermissionDeniedException("Authentication required"); throw new PermissionDeniedException("Authentication required"); } } } } Loading @@ -64,5 +158,4 @@ public class CollectionsService { return userId != null return userId != null && !userId.equals("anonymous"); && !userId.equals("anonymous"); } } } }
src/main/java/it/inaf/oats/vospace/persistence/CollectionsDAO.java +32 −11 Original line number Original line Diff line number Diff line Loading @@ -6,6 +6,7 @@ package it.inaf.oats.vospace.persistence; package it.inaf.oats.vospace.persistence; import it.inaf.oats.vospace.datamodel.collections.NodeCollection; import it.inaf.oats.vospace.datamodel.collections.NodeCollection; import it.inaf.oats.vospace.datamodel.collections.NodeDetails; import java.sql.PreparedStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLException; Loading Loading @@ -66,6 +67,32 @@ public class CollectionsDAO { } } public List<NodeDetails> getNodeDetailsInCollection(Long collectionId) { String sql = "SELECT node_id, get_vos_path(node_id) as node_vos_path\n" + "FROM collections_node WHERE collection_id = ?"; return jdbcTemplate.query( conn-> { PreparedStatement ps = conn.prepareStatement(sql); ps.setLong(1, collectionId); return ps; }, (row, index) -> { return this.getNodeDetailsFromResultset(row); }); } private NodeDetails getNodeDetailsFromResultset(ResultSet rs) throws SQLException { NodeDetails nd = new NodeDetails(); nd.setNodeId(rs.getLong("node_id")); nd.setNodeVosPath(rs.getString("node_vos_path")); return nd; } public List<NodeCollection> getUserNodeCollections(String userId) { public List<NodeCollection> getUserNodeCollections(String userId) { String sql = "SELECT collection_id, title, owner_id FROM collections\n" String sql = "SELECT collection_id, title, owner_id FROM collections\n" + "WHERE owner_id = ?"; + "WHERE owner_id = ?"; Loading Loading @@ -96,23 +123,17 @@ public class CollectionsDAO { }); }); } } public void removeNodeFromCollection(Long nodeId, Long collectionId) { public int removeNodeFromCollection(Long nodeId, Long collectionId) { String sql = "DELETE FROM collections_node WHERE collection_id = ? and node_id = ?"; String sql = "DELETE FROM collections_node WHERE collection_id = ? and node_id = ?"; jdbcTemplate.update(sql, collectionId, nodeId); // Returns the number of deleted nodes: must be 1 } return jdbcTemplate.update(sql, collectionId, nodeId); // TODO complete stub public List<NodeCollection> getCollectionsOfNode(Long nodeId) { throw new UnsupportedOperationException(); } } // TODO complete stub: add list of nodes in collection (path list?) public int deleteCollection(Long collectionId, String userId) { public void deleteCollection(Long collectionId, String userId) { String sql = "DELETE FROM collections WHERE collection_id = ? AND owner_id = ?"; String sql = "DELETE FROM collections WHERE collection_id = ? AND owner_id = ?"; jdbcTemplate.update(sql, collectionId, userId); return jdbcTemplate.update(sql, collectionId, userId); } } private NodeCollection getNodeCollectionFromResultset(ResultSet rs) private NodeCollection getNodeCollectionFromResultset(ResultSet rs) Loading
src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java +38 −2 Original line number Original line Diff line number Diff line Loading @@ -246,11 +246,14 @@ public class NodeDAO { String userId, List<String> userGroups) { String userId, List<String> userGroups) { String sql = "SELECT path,\n" String sql = "SELECT path,\n" + "n.node_id AS node_id\n" + "n.creator_id as creator_id\n" + "NOT (n.async_trans OR COALESCE(location_type = 'async', FALSE)) AS is_writable,\n" + "NOT (n.async_trans OR COALESCE(location_type = 'async', FALSE)) AS is_writable,\n" + "n.sticky AS is_sticky,\n" + "n.sticky AS is_sticky,\n" + "((SELECT COUNT(*) FROM (SELECT UNNEST(?) INTERSECT SELECT UNNEST(n.group_write)) AS allowed_groups ) = 0 AND\n" + "((SELECT COUNT(*) FROM (SELECT UNNEST(?) INTERSECT SELECT UNNEST(n.group_write)) AS allowed_groups ) = 0 AND\n" + "n.creator_id <> ?) AS is_permission_denied,\n" + "n.creator_id <> ?) AS is_permission_denied,\n" + "n.type = 'container' AS is_container,\n" + "n.type = 'container' AS is_container,\n" + "n.type = 'link' AS is_link,\n" + "n.job_id IS NOT NULL AS busy_state,\n" + "n.job_id IS NOT NULL AS busy_state,\n" + "n.immutable AS is_immutable\n" + "n.immutable AS is_immutable\n" + "FROM node n \n" + "FROM node n \n" Loading @@ -277,14 +280,20 @@ public class NodeDAO { } } String nodePath = rs.getString("path"); String nodePath = rs.getString("path"); Long nodeId = rs.getLong("node_id"); String creatorId = rs.getString(("creator_id")); Boolean isContainer = rs.getBoolean(("is_container")); Boolean isContainer = rs.getBoolean(("is_container")); Boolean isLink = rs.getBoolean(("is_link")); Boolean isWritable = rs.getBoolean("is_writable"); Boolean isWritable = rs.getBoolean("is_writable"); Boolean isBusy = rs.getBoolean("busy_state"); Boolean isBusy = rs.getBoolean("busy_state"); Boolean isPermissionDenied = rs.getBoolean("is_permission_denied"); Boolean isPermissionDenied = rs.getBoolean("is_permission_denied"); Boolean isSticky = rs.getBoolean("is_sticky"); Boolean isSticky = rs.getBoolean("is_sticky"); Boolean isImmutable = rs.getBoolean("is_immutable"); Boolean isImmutable = rs.getBoolean("is_immutable"); ShortNodeDescriptor result = new ShortNodeDescriptor(nodePath, isContainer, isWritable, isBusy, isPermissionDenied, isSticky, isImmutable); ShortNodeDescriptor result = new ShortNodeDescriptor(nodePath, nodeId, creatorId, isContainer, isLink, isWritable, isBusy, isPermissionDenied, isSticky, isImmutable); return Optional.of(result); return Optional.of(result); }); }); Loading Loading @@ -757,17 +766,32 @@ public class NodeDAO { public class ShortNodeDescriptor { public class ShortNodeDescriptor { private final String nodeLtreePath; private final String nodeLtreePath; private final Long nodeId; private final String creatorId; private final boolean container; private final boolean container; private final boolean link; private final boolean writable; private final boolean writable; private final boolean busy; private final boolean busy; private final boolean permissionDenied; private final boolean permissionDenied; private final boolean sticky; private final boolean sticky; private final boolean immutable; private final boolean immutable; public ShortNodeDescriptor(String nodeLtreePath, boolean container, boolean writable, boolean busy, boolean permissionDenied, boolean sticky, boolean immutable) { public ShortNodeDescriptor( String nodeLtreePath, Long nodeId, String creatorId, boolean container, boolean link, boolean writable, boolean busy, boolean permissionDenied, boolean sticky, boolean immutable) { this.nodeLtreePath = nodeLtreePath; this.nodeLtreePath = nodeLtreePath; this.nodeId = nodeId; this.creatorId = creatorId; this.container = container; this.container = container; this.link = link; this.writable = writable; this.writable = writable; this.busy = busy; this.busy = busy; this.permissionDenied = permissionDenied; this.permissionDenied = permissionDenied; Loading @@ -779,10 +803,22 @@ public class NodeDAO { return nodeLtreePath; return nodeLtreePath; } } public Long getNodeId() { return this.nodeId; } public String getCreatorId() { return creatorId; } public boolean isContainer() { public boolean isContainer() { return container; return container; } } public boolean isLink() { return link; } public boolean isImmutable() { public boolean isImmutable() { return immutable; return immutable; } } Loading