diff --git a/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java b/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java index b4b3356276876caf282bb4b0136ff723789a342f..872f2cb349d40239c9f68cf82682212c5ecbd7da 100644 --- a/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java +++ b/src/main/java/it/inaf/oats/vospace/persistence/NodeDAO.java @@ -35,7 +35,7 @@ import org.springframework.stereotype.Repository; public class NodeDAO { private static final Logger LOG = LoggerFactory.getLogger(DeleteNodeController.class); - + @Value("${vospace-authority}") private String authority; @@ -124,35 +124,35 @@ public class NodeDAO { public Node setNode(Node newNode) { return setNode(newNode, false); - } - + } + /** * If recursive flag is true the update is applied to children too. */ public Node setNode(Node newNode, boolean recursive) { - + String vosPath = NodeUtils.getVosPath(newNode); StringBuilder sb = new StringBuilder(); - + sb.append("UPDATE node"); - sb.append(" SET owner_id = ?, group_read = ?, group_write = ?, is_public = ? " ); + sb.append(" SET group_read = ?, group_write = ?, is_public = ? "); sb.append(" FROM node_vos_path p WHERE p.vos_path = ? AND p.node_id = node.node_id "); - jdbcTemplate.update(conn -> { - PreparedStatement ps = conn.prepareStatement(sb.toString()); - int i = 0; - ps.setString(++i, NodeProperties.getNodePropertyByURI(newNode, NodeProperties.CREATOR_URI)); - ps.setArray(++i, fromPropertyToArray(ps, NodeProperties.getNodePropertyByURI(newNode, NodeProperties.GROUP_READ_URI))); - ps.setArray(++i, fromPropertyToArray(ps, NodeProperties.getNodePropertyByURI(newNode, NodeProperties.GROUP_WRITE_URI))); - ps.setBoolean(++i, Boolean.valueOf(NodeProperties.getNodePropertyByURI(newNode, NodeProperties.PUBLIC_READ_URI))); - ps.setString(++i, vosPath); - return ps; - }); - - if (recursive == true) + if (recursive) { updatePermissionsRecursively(newNode, vosPath); - + } else { + jdbcTemplate.update(conn -> { + PreparedStatement ps = conn.prepareStatement(sb.toString()); + int i = 0; + ps.setArray(++i, fromPropertyToArray(ps, NodeProperties.getNodePropertyByURI(newNode, NodeProperties.GROUP_READ_URI))); + ps.setArray(++i, fromPropertyToArray(ps, NodeProperties.getNodePropertyByURI(newNode, NodeProperties.GROUP_WRITE_URI))); + ps.setBoolean(++i, Boolean.valueOf(NodeProperties.getNodePropertyByURI(newNode, NodeProperties.PUBLIC_READ_URI))); + ps.setString(++i, vosPath); + return ps; + }); + } + return newNode; } @@ -198,7 +198,7 @@ public class NodeDAO { addProperty(NodeProperties.LENGTH_URI, contentLength == null ? "0" : contentLength, properties); String creationTime = rs.getString("created_on").replace(" ", "T"); - + addProperty(NodeProperties.INITIAL_CREATION_TIME_URI, creationTime, properties); addProperty(NodeProperties.DATE_URI, creationTime, properties); // required by CADC @@ -276,7 +276,7 @@ public class NodeDAO { return jdbcTemplate.queryForObject(sql, args, types, Integer.class); } - + public String getNodeOsName(String vosPath) { String sql = "SELECT \n" + "(CASE WHEN os_name IS NOT NULL THEN os_name ELSE name END) AS os_name\n" @@ -289,7 +289,7 @@ public class NodeDAO { return jdbcTemplate.queryForObject(sql, args, types, String.class); } - + public void setNodeLocation(String vosPath, int locationId, String nodeOsName) { String sql = "UPDATE node SET location_id = ?, os_name = ? WHERE node_id = " @@ -323,7 +323,6 @@ public class NodeDAO { list.add(prop); } } - private String getUri(String path) { return "vos://" + authority + path; @@ -333,7 +332,6 @@ public class NodeDAO { NodePaths paths = new NodePaths(rs.getString("path"), rs.getString("relative_path")); return paths; } - private Array fromPropertyToArray(PreparedStatement ps, String myProperty) throws SQLException { if (myProperty == null || myProperty.isBlank()) { @@ -361,92 +359,103 @@ public class NodeDAO { } try { return Arrays.stream((String[]) array.getArray()) - .map(uri -> { - View view = new View(); - view.setUri(uri); - return view; - }) - .collect(Collectors.toList()); + .map(uri -> { + View view = new View(); + view.setUri(uri); + return view; + }) + .collect(Collectors.toList()); } catch (SQLException ex) { throw new RuntimeException(ex); } - + } - + /* Map contains: Key column column name value column name value and value is a String containing comma separated groups having permissions - */ - private Map getPermissionsFromDB(String vosPath) { - + */ + private Map<String, List<String>> getPermissionsFromDB(String vosPath) { + String sql = "SELECT group_read, group_write " + "FROM node n JOIN node_vos_path p ON n.node_id = p.node_id " + "WHERE p.vos_path = ?"; - - Map<String, Object> result = (Map<String, Object>) jdbcTemplate - .queryForMap(sql, new Object[] {vosPath}); - - return result; - + + return jdbcTemplate.query(sql, new Object[]{vosPath}, rs -> { + if (!rs.next()) { + throw new InternalFaultException("No records found for " + vosPath); + } + return Map.of( + "group_read", getArrayValue(rs, "group_read"), + "group_write", getArrayValue(rs, "group_write") + ); + }); + } + + private List<String> getArrayValue(ResultSet rs, String key) throws SQLException { + Array array = rs.getArray(key); + if (array == null) { + return new ArrayList<>(); + } + return Arrays.asList((String[]) array.getArray()); } - + private void updatePermissionsRecursively(Node newNode, String vosPath) { - - Map permissions = getPermissionsFromDB(vosPath); - String existingGroupReadStr = (String)permissions.get("group_read"); - String existingGroupWriteStr = (String)permissions.get("group_write"); - - List<String> existingGroupReadList = NodeProperties.parsePropertyStringToList(existingGroupReadStr); - List<String> existingGroupWriteList = NodeProperties.parsePropertyStringToList(existingGroupWriteStr); - + + Map<String, List<String>> permissions = getPermissionsFromDB(vosPath); + + List<String> existingGroupReadList = permissions.get("group_read"); + List<String> existingGroupWriteList = permissions.get("group_write"); + List<String> newGroupReadList = NodeProperties.getNodePropertyAsListByURI(newNode, NodeProperties.GROUP_READ_URI); List<String> newGroupWriteList = NodeProperties.getNodePropertyAsListByURI(newNode, NodeProperties.GROUP_WRITE_URI); - + Set<String> existingGroupRead = new HashSet<>(existingGroupReadList); Set<String> existingGroupWrite = new HashSet<>(existingGroupWriteList); - + Set<String> newGroupRead = new HashSet<>(newGroupReadList); Set<String> newGroupWrite = new HashSet<>(newGroupWriteList); - - Set<String> groupReadToAdd = differenceBetweenSets(newGroupRead, existingGroupRead) ; - Set<String> groupReadToRemove = differenceBetweenSets(existingGroupRead, newGroupRead) ; - - Set<String> groupWriteToAdd = differenceBetweenSets(newGroupWrite, existingGroupWrite) ; - Set<String> groupWriteToRemove = differenceBetweenSets(existingGroupWrite, newGroupWrite) ; - - String sql = "UPDATE node SET " + - "group_read = update_array(group_read, " + groupReadToAdd + ", " + groupReadToRemove + "), " + - "group_write = update_array(group_write, " + groupWriteToAdd + ", " + groupWriteToRemove + "), " + - "is_public = ? " + - "WHERE path <@ (SELECT path FROM node n " + - "JOIN node_vos_path p ON n.node_id = p.node_id " + - "AND p.vos_path = ?)"; - + + Set<String> groupReadToAdd = differenceBetweenSets(newGroupRead, existingGroupRead); + Set<String> groupReadToRemove = differenceBetweenSets(existingGroupRead, newGroupRead); + + Set<String> groupWriteToAdd = differenceBetweenSets(newGroupWrite, existingGroupWrite); + Set<String> groupWriteToRemove = differenceBetweenSets(existingGroupWrite, newGroupWrite); + + String sql = "UPDATE node SET " + + "group_read = update_array(group_read, ?, ?), " + + "group_write = update_array(group_write, ?, ?), " + + "is_public = ? " + + "WHERE path <@ (SELECT path FROM node n " + + "JOIN node_vos_path p ON n.node_id = p.node_id " + + "AND p.vos_path = ?)"; jdbcTemplate.update(conn -> { PreparedStatement ps = conn.prepareStatement(sql); int i = 0; + ps.setArray(++i, ps.getConnection().createArrayOf("varchar", groupReadToAdd.toArray())); + ps.setArray(++i, ps.getConnection().createArrayOf("varchar", groupReadToRemove.toArray())); + ps.setArray(++i, ps.getConnection().createArrayOf("varchar", groupWriteToAdd.toArray())); + ps.setArray(++i, ps.getConnection().createArrayOf("varchar", groupWriteToRemove.toArray())); ps.setBoolean(++i, Boolean.valueOf(NodeProperties.getNodePropertyByURI(newNode, NodeProperties.PUBLIC_READ_URI))); ps.setString(++i, vosPath); return ps; }); - } // Returns the difference a minus b private Set<String> differenceBetweenSets(Set<String> a, Set<String> b) { - + Set<String> diff = new HashSet<>(a); diff.removeAll(b); - + return diff; - } - - private List<NodePaths> getNodePathsFromDB(String nodeURI) { + + private List<NodePaths> getNodePathsFromDB(String nodeURI) { String path = nodeURI.replaceAll("vos://[^/]+", ""); String parentPath = NodeUtils.getParentPath(path); @@ -462,7 +471,7 @@ public class NodeDAO { }, (row, index) -> { return getPathsFromResultSet(row); }); - + return paths; } @@ -481,15 +490,13 @@ public class NodeDAO { public String toString() { return relativePath + " " + path; } - + public String getPath() { return this.path; - } - + } + public String getRelativePath() { return this.relativePath; - } - - } - + } + } } diff --git a/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java b/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java index 718b79befc6dfb09ecc66c4da5cfcfc3388e76e3..5cb838a4ff7395503f0b506a92a469b45807ee07 100644 --- a/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java +++ b/src/test/java/it/inaf/oats/vospace/persistence/NodeDAOTest.java @@ -142,7 +142,7 @@ public class NodeDAOTest { assertEquals("true", NodeProperties.getNodePropertyByURI(node, NodeProperties.PUBLIC_READ_URI)); } - //@Test + @Test public void testSetNodeRecursiveGroup() { Property parentGroupRead = getProperty(NodeProperties.GROUP_READ_URI, "group1 group2"); @@ -153,7 +153,7 @@ public class NodeDAOTest { node.getProperties().add(parentGroupRead); node.getProperties().add(parentGroupWrite); dao.createNode(node); - + Node child1 = new DataNode(); child1.setUri("vos://example.com!vospace/mydata4/child1"); child1.getProperties().add(getProperty(NodeProperties.GROUP_READ_URI, "group3"));