Skip to content
Snippets Groups Projects
Commit f919f87c authored by Nicola Fulvio Calabria's avatar Nicola Fulvio Calabria
Browse files

Refactored Delete

parent fb5a87c6
No related branches found
No related tags found
1 merge request!1Immutable
...@@ -27,10 +27,10 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -27,10 +27,10 @@ import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
public class DeleteNodeController extends BaseNodeController { public class DeleteNodeController extends BaseNodeController {
private static final Logger LOG = LoggerFactory.getLogger(DeleteNodeController.class);
@Autowired @Autowired
private NodeDAO nodeDAO; DeleteNodeService deleteNodeService;
private static final Logger LOG = LoggerFactory.getLogger(DeleteNodeController.class);
@DeleteMapping(value = {"/nodes", "/nodes/**"}, @DeleteMapping(value = {"/nodes", "/nodes/**"},
produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}) produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
...@@ -39,44 +39,10 @@ public class DeleteNodeController extends BaseNodeController { ...@@ -39,44 +39,10 @@ public class DeleteNodeController extends BaseNodeController {
String path = getPath(); String path = getPath();
LOG.debug("deleteNode called for path {}", path); LOG.debug("deleteNode called for path {}", path);
// Check if the node is present,
// if the node does not exist the service SHALL throw a HTTP 404 status code
// including a NodeNotFound fault in the entity-body
// If note present, got it
Node toBeDeletedNode = nodeDAO.listNode(path)
.orElseThrow(() -> new NodeNotFoundException(path));
// If a parent node in the URI path is a LinkNode, the service SHALL throw
// a HTTP 400 status code including a LinkFound fault in the entity-body.
// For example, given the URI path /a/b/c, the service must throw a HTTP 400
// status code including a LinkFound fault in the entity-body if either /a
// or /a/b are LinkNodes.
List<String> pathComponents = NodeUtils.subPathComponents(path);
if (pathComponents.isEmpty()) {
// Manage root node
throw PermissionDeniedException.forPath("/");
} else {
// Manage all precursors in full path
for (int i = 0; i < pathComponents.size(); i++) {
String tmpPath = pathComponents.get(i);
Node mynode = nodeDAO.listNode(tmpPath)
.orElseThrow(() -> new NodeNotFoundException(tmpPath));
if (mynode.getType().equals("vos:LinkNode") && i < pathComponents.size()-1) // a LinkNode leaf can be deleted
throw new LinkFoundException(tmpPath);
}
}
if (!NodeUtils.checkIfWritable(toBeDeletedNode, principal.getName(), principal.getGroups())) {
throw PermissionDeniedException.forPath(path);
}
try { try {
nodeDAO.deleteNode(path); deleteNodeService.doPreliminaryChecks(path);
deleteNodeService.deleteNode(path, principal);
return ResponseEntity.ok("Node deleted"); return ResponseEntity.ok("Node deleted");
} catch(Exception ex) { } catch(Exception ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST); return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
......
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package it.inaf.oats.vospace;
import it.inaf.oats.vospace.datamodel.NodeUtils;
import it.inaf.oats.vospace.exception.LinkFoundException;
import it.inaf.oats.vospace.exception.NodeNotFoundException;
import it.inaf.oats.vospace.exception.PermissionDeniedException;
import it.inaf.oats.vospace.persistence.NodeDAO;
import java.util.List;
import net.ivoa.xml.vospace.v2.Node;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Isolation;
import it.inaf.ia2.aa.data.User;
import org.springframework.transaction.annotation.Transactional;
/**
*
* @author Nicola Fulvio Calabria <nicola.calabria at inaf.it>
*/
@Service
@EnableTransactionManagement
public class DeleteNodeService {
@Autowired
protected NodeDAO nodeDao;
@Value("${vospace-authority}")
protected String authority;
@Transactional(rollbackFor = { Exception.class },
isolation = Isolation.REPEATABLE_READ)
public void deleteNode(String path, User principal) {
Node toBeDeletedNode = nodeDao.listNode(path)
.orElseThrow(() -> new NodeNotFoundException(path));
if (!NodeUtils.checkIfWritable(toBeDeletedNode, principal.getName(), principal.getGroups())) {
throw PermissionDeniedException.forPath(path);
}
nodeDao.deleteNode(path);
}
public void doPreliminaryChecks(String path) throws Exception {
// Check if the node is present,
// if the node does not exist the service SHALL throw a HTTP 404 status code
// including a NodeNotFound fault in the entity-body
// If note present, got it
nodeDao.listNode(path)
.orElseThrow(() -> new NodeNotFoundException(path));
// If a parent node in the URI path is a LinkNode, the service SHALL throw
// a HTTP 400 status code including a LinkFound fault in the entity-body.
// For example, given the URI path /a/b/c, the service must throw a HTTP 400
// status code including a LinkFound fault in the entity-body if either /a
// or /a/b are LinkNodes.
List<String> pathComponents = NodeUtils.subPathComponents(path);
if (pathComponents.isEmpty()) {
// Manage root node
throw PermissionDeniedException.forPath("/");
} else {
// Manage all precursors in full path
for (int i = 0; i < pathComponents.size(); i++) {
String tmpPath = pathComponents.get(i);
Node mynode = nodeDao.listNode(tmpPath)
.orElseThrow(() -> new NodeNotFoundException(tmpPath));
if (mynode.getType().equals("vos:LinkNode") && i < pathComponents.size()-1) // a LinkNode leaf can be deleted
throw new LinkFoundException(tmpPath);
}
}
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package it.inaf.oats.vospace;
import it.inaf.ia2.aa.data.User;
import it.inaf.oats.vospace.persistence.NodeDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
/**
*
* @author Nicola Fulvio Calabria <nicola.calabria at inaf.it>
*/
@Service
@EnableTransactionManagement
public class ImmutableService {
@Autowired
protected NodeDAO nodeDao;
@Value("${vospace-authority}")
protected String authority;
@Transactional(rollbackFor = {Exception.class}, isolation = Isolation.REPEATABLE_READ)
public void setBranchImmutable(String rootNodeURI, boolean setImmutable, User user) {
String rootNodeVosPath = URIUtils.returnVosPathFromNodeURI(rootNodeURI, authority);
// Check if branch is busy
}
}
...@@ -68,6 +68,11 @@ public class MoveService extends AbstractNodeService { ...@@ -68,6 +68,11 @@ public class MoveService extends AbstractNodeService {
throw new NodeBusyException(sourcePath); throw new NodeBusyException(sourcePath);
} }
// TODO create immutable node exception flavor
if (nodeDao.isBranchImmutable(sourceId)) {
throw new InternalFaultException("Source branch contains immutable nodes");
}
if (!nodeDao.isBranchWritable(sourceId, user.getName(), user.getGroups())) { if (!nodeDao.isBranchWritable(sourceId, user.getName(), user.getGroups())) {
throw PermissionDeniedException.forPath(sourcePath); throw PermissionDeniedException.forPath(sourcePath);
} }
...@@ -84,6 +89,7 @@ public class MoveService extends AbstractNodeService { ...@@ -84,6 +89,7 @@ public class MoveService extends AbstractNodeService {
if(snd.isPermissionDenied()) throw PermissionDeniedException.forPath(destinationPath); if(snd.isPermissionDenied()) throw PermissionDeniedException.forPath(destinationPath);
if(!snd.isWritable()) throw new InternalFaultException("Destination is not writable: "+ destinationPath); if(!snd.isWritable()) throw new InternalFaultException("Destination is not writable: "+ destinationPath);
if(!snd.isContainer()) throw new InternalFaultException("Existing destination is not a container: " + destinationPath); if(!snd.isContainer()) throw new InternalFaultException("Existing destination is not a container: " + destinationPath);
if(!snd.isImmutable()) throw new InternalFaultException("Destination is immutable: " + destinationPath);
destinationNodeLtreePath = snd.getDestinationNodeLtreePath(); destinationNodeLtreePath = snd.getDestinationNodeLtreePath();
......
...@@ -257,6 +257,7 @@ public class NodeDAO { ...@@ -257,6 +257,7 @@ public class NodeDAO {
+ "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.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"
+ "FROM node n \n" + "FROM node n \n"
+ "LEFT JOIN location loc ON loc.location_id = n.location_id\n" + "LEFT JOIN location loc ON loc.location_id = n.location_id\n"
+ "WHERE n.node_id = id_from_vos_path(?)\n"; + "WHERE n.node_id = id_from_vos_path(?)\n";
...@@ -286,8 +287,9 @@ public class NodeDAO { ...@@ -286,8 +287,9 @@ public class NodeDAO {
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");
ShortNodeDescriptor result = new ShortNodeDescriptor(nodePath, isContainer, isWritable, isBusy, isPermissionDenied, isSticky); ShortNodeDescriptor result = new ShortNodeDescriptor(nodePath, isContainer, isWritable, isBusy, isPermissionDenied, isSticky, isImmutable);
return Optional.of(result); return Optional.of(result);
}); });
...@@ -766,14 +768,16 @@ public class NodeDAO { ...@@ -766,14 +768,16 @@ public class NodeDAO {
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;
public ShortNodeDescriptor(String nodeLtreePath, boolean container, boolean writable, boolean busy, boolean permissionDenied, boolean sticky) { public ShortNodeDescriptor(String nodeLtreePath, boolean container, boolean writable, boolean busy, boolean permissionDenied, boolean sticky, boolean immutable) {
this.nodeLtreePath = nodeLtreePath; this.nodeLtreePath = nodeLtreePath;
this.container = container; this.container = container;
this.writable = writable; this.writable = writable;
this.busy = busy; this.busy = busy;
this.permissionDenied = permissionDenied; this.permissionDenied = permissionDenied;
this.sticky = sticky; this.sticky = sticky;
this.immutable = immutable;
} }
public String getDestinationNodeLtreePath() { public String getDestinationNodeLtreePath() {
...@@ -784,6 +788,10 @@ public class NodeDAO { ...@@ -784,6 +788,10 @@ public class NodeDAO {
return container; return container;
} }
public boolean isImmutable() {
return immutable;
}
public boolean isWritable() { public boolean isWritable() {
return writable; return writable;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment