/* * This file is part of vospace-rest * Copyright (C) 2021 Istituto Nazionale di Astrofisica * SPDX-License-Identifier: GPL-3.0-or-later */ package it.inaf.oats.vospace; import it.inaf.ia2.aa.data.User; import it.inaf.oats.vospace.datamodel.NodeProperties; import it.inaf.oats.vospace.datamodel.NodeUtils; import it.inaf.oats.vospace.exception.ContainerNotFoundException; import it.inaf.oats.vospace.exception.DuplicateNodeException; import it.inaf.oats.vospace.exception.LinkFoundException; import it.inaf.oats.vospace.exception.PermissionDeniedException; import it.inaf.oats.vospace.persistence.NodeDAO; import net.ivoa.xml.vospace.v2.Node; import net.ivoa.xml.vospace.v2.Property; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.EnableTransactionManagement; @Service @EnableTransactionManagement public class CreateNodeService { @Autowired private NodeDAO nodeDao; private static final Logger LOG = LoggerFactory.getLogger(CreateNodeService.class); public Node createNode(Node node, String path, User principal) { LOG.debug("createNodeService called for node with URI {} and PATH {}", node.getUri(), path); // Check if another node is already present at specified path // This checks if the user is trying to insert the root node at "/" too if (nodeDao.listNode(path).isPresent()) { throw new DuplicateNodeException(path); } // Retrieve parent node Node parentNode = nodeDao.listNode(getParentPath(path)) .orElseThrow(() -> new ContainerNotFoundException(getParentPath(path))); // Check if parent node is not a Container node and in case throw // appropriate exception if (!parentNode.getType().equals("vos:ContainerNode")) { if (parentNode.getType().equals("vos:LinkNode")) { throw new LinkFoundException(getParentPath(path)); } else { throw new ContainerNotFoundException(getParentPath(path)); } } if (!NodeUtils.checkIfWritable(parentNode, principal.getName(), principal.getGroups())) { throw PermissionDeniedException.forPath(path); } // Check if node creator property is set. If not set it according to // token. In case of creator mistmatch between node and token throw // exception String creator = NodeProperties.getNodePropertyByURI( node, NodeProperties.CREATOR_URI); if (creator == null) { Property creatorProperty = new Property(); creatorProperty.setUri(NodeProperties.CREATOR_URI); creatorProperty.setValue(principal.getName()); node.getProperties().add(creatorProperty); } else { if (!creator.equals(principal.getName())) // maybe a more specific exception would be more appropriate? { throw PermissionDeniedException.forPath(path); } } // If payload has no read groups specified, inherit from parent node String payloadReadGroups = NodeProperties.getNodePropertyByURI( node, NodeProperties.GROUP_READ_URI); if (payloadReadGroups == null) { String parentNodeReadGroups = NodeProperties.getNodePropertyByURI( parentNode, NodeProperties.GROUP_READ_URI); if (parentNodeReadGroups != null) { Property readGroups = new Property(); readGroups.setUri(NodeProperties.GROUP_READ_URI); readGroups.setValue(parentNodeReadGroups); node.getProperties().add(readGroups); } } // If payload has no write groups specified, inherit from parent node String payloadWriteGroups = NodeProperties.getNodePropertyByURI( node, NodeProperties.GROUP_WRITE_URI); if (payloadWriteGroups == null) { String parentNodeWriteGroups = NodeProperties.getNodePropertyByURI( parentNode, NodeProperties.GROUP_WRITE_URI); if (parentNodeWriteGroups != null) { Property writeGroups = new Property(); writeGroups.setUri(NodeProperties.GROUP_WRITE_URI); writeGroups.setValue(parentNodeWriteGroups); node.getProperties().add(writeGroups); } } nodeDao.createNode(node); return node; } private String getParentPath(String path) { return NodeUtils.getParentPath(path); } }