Newer
Older
import it.inaf.ia2.aa.ServletRapClient;
import it.inaf.ia2.aa.data.User;
import it.inaf.ia2.rap.client.call.TokenExchangeRequest;
Nicola Fulvio Calabria
committed
import it.inaf.oats.vospace.JobService.JobType;
import it.inaf.oats.vospace.datamodel.NodeProperties;
Nicola Fulvio Calabria
committed
import it.inaf.oats.vospace.datamodel.NodeUtils;
import static it.inaf.oats.vospace.datamodel.NodeUtils.urlEncodePath;
import it.inaf.oats.vospace.exception.InternalFaultException;
Nicola Fulvio Calabria
committed
import it.inaf.oats.vospace.exception.InvalidURIException;
import it.inaf.oats.vospace.exception.NodeNotFoundException;
import it.inaf.oats.vospace.exception.PermissionDeniedException;
Nicola Fulvio Calabria
committed
import it.inaf.oats.vospace.exception.ProtocolNotSupportedException;
import it.inaf.oats.vospace.exception.NodeBusyException;
import it.inaf.oats.vospace.persistence.LocationDAO;
import it.inaf.oats.vospace.persistence.NodeDAO;
import it.inaf.oats.vospace.persistence.model.Location;
import it.inaf.oats.vospace.persistence.model.LocationType;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
Nicola Fulvio Calabria
committed
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
import net.ivoa.xml.uws.v1.JobSummary;
import net.ivoa.xml.uws.v1.ResultReference;
Nicola Fulvio Calabria
committed
import net.ivoa.xml.vospace.v2.DataNode;
import net.ivoa.xml.vospace.v2.Protocol;
import net.ivoa.xml.vospace.v2.Transfer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class UriService {
@Value("${vospace-authority}")
private String authority;
@Value("${file-service-url}")
private String fileServiceUrl;
@Autowired
private NodeDAO nodeDao;
Nicola Fulvio Calabria
committed
@Autowired
private LocationDAO locationDAO;
@Autowired
private HttpServletRequest servletRequest;
@Autowired
private ServletRapClient rapClient;
Nicola Fulvio Calabria
committed
@Autowired
private CreateNodeController createNodeController;
public void setTransferJobResult(JobSummary job, Transfer transfer) {
List<ResultReference> results = new ArrayList<>();
Nicola Fulvio Calabria
committed
ResultReference result = new ResultReference();
result.setHref(getEndpoint(job, transfer));
results.add(result);
job.setResults(results);
Nicola Fulvio Calabria
committed
// Moved phase setting to caller method for ERROR management
// job.setPhase(ExecutionPhase.COMPLETED);
public void setSyncTransferEndpoints(JobSummary job) {
Transfer transfer = getTransfer(job);
Protocol protocol = transfer.getProtocols().get(0);
if (!"ivo://ivoa.net/vospace/core#httpget".equals(protocol.getUri())
&& !"ivo://ivoa.net/vospace/core#httpput".equals(protocol.getUri())) {
Nicola Fulvio Calabria
committed
// throw new IllegalStateException("Unsupported protocol " + protocol.getUri());
throw new ProtocolNotSupportedException(protocol.getUri());
protocol.setEndpoint(getEndpoint(job, transfer));
Nicola Fulvio Calabria
committed
private Node getEndpointNode(String relativePath,
JobService.JobType jobType,
User user) {
Optional<Node> optNode = nodeDao.listNode(relativePath);
if (optNode.isPresent()) {
return optNode.get();
} else {
switch (jobType) {
case pullFromVoSpace:
throw new NodeNotFoundException(relativePath);
case pushToVoSpace:
case pullToVoSpace:
DataNode newNode = new DataNode();
newNode.setUri(relativePath);
return createNodeController.createNode(newNode, user);
default:
throw new InternalFaultException("No supported job direction specified");
}
}
}
private String getEndpoint(JobSummary job, Transfer transfer) {
String relativePath = transfer.getTarget().substring("vos://".length() + authority.length());
Nicola Fulvio Calabria
committed
User user = (User) servletRequest.getUserPrincipal();
String creator = user.getName();
List<String> groups = user.getGroups();
// Check privileges write or read according to job type
JobService.JobType jobType = JobType.valueOf(transfer.getDirection());
Nicola Fulvio Calabria
committed
Node node = this.getEndpointNode(relativePath, jobType, user);
Nicola Fulvio Calabria
committed
switch (jobType) {
case pushToVoSpace:
case pullToVoSpace:
if (!NodeUtils.checkIfWritable(node, creator, groups)) {
throw new PermissionDeniedException(relativePath);
}
break;
case pullFromVoSpace:
if (!NodeUtils.checkIfReadable(node, creator, groups)) {
throw new PermissionDeniedException(relativePath);
}
break;
default:
Nicola Fulvio Calabria
committed
throw new InternalFaultException("No supported job direction specified");
Nicola Fulvio Calabria
committed
}
if (NodeUtils.getIsBusy(node)) {
throw new NodeBusyException(relativePath);
}
Location location = locationDAO.getNodeLocation(relativePath).orElse(null);
if (location != null && location.getType() == LocationType.PORTAL) {
String fileName = nodeDao.getNodeOsName(relativePath);
endpoint = "http://" + location.getSource().getHostname() + location.getSource().getBaseUrl();
if (!endpoint.endsWith("/")) {
endpoint += "/";
}
endpoint += fileName;
} else {
endpoint = fileServiceUrl + urlEncodePath(relativePath);
}
endpoint += "?jobId=" + job.getJobId();
if (!"true".equals(NodeProperties.getNodePropertyByURI(node, NodeProperties.PUBLIC_READ_URI))) {
endpoint += "&token=" + getEndpointToken(fileServiceUrl + relativePath);
}
return endpoint;
}
private String getEndpointToken(String endpoint) {
String token = ((User) servletRequest.getUserPrincipal()).getAccessToken();
if (token == null) {
throw new PermissionDeniedException("Token is null");
}
TokenExchangeRequest exchangeRequest = new TokenExchangeRequest()
.setSubjectToken(token)
.setResource(endpoint);
// TODO: add audience and scope
return rapClient.exchangeToken(exchangeRequest, servletRequest);
}
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
public void setNodeRemoteLocation(String nodeUri, String contentUri) {
URL url;
try {
url = new URL(contentUri);
} catch (MalformedURLException ex) {
throw new InternalFaultException(ex);
}
Location location = locationDAO.findPortalLocation(url.getHost()).orElseThrow(()
-> new InternalFaultException("No registered location found for host " + url.getHost()));
String vosPath = nodeUri.replaceAll("vos://[^/]+", "");
String fileName = url.getPath().substring(url.getPath().lastIndexOf("/") + 1);
nodeDao.setNodeLocation(vosPath, location.getId(), fileName);
}
public Transfer getTransfer(JobSummary job) {
List<Object> jobPayload = job.getJobInfo().getAny();
if (jobPayload.isEmpty()) {
throw new IllegalStateException("Empty job payload for job " + job.getJobId());
}
if (jobPayload.size() > 1) {
throw new IllegalStateException("Multiple objects in job payload not supported");
}
if (!(jobPayload.get(0) instanceof Transfer)) {
throw new IllegalStateException(jobPayload.get(0).getClass().getCanonicalName()
+ " not supported as job payload. Job id: " + job.getJobId());
}
return (Transfer) job.getJobInfo().getAny().get(0);
}