Commit 8bbdb542 authored by L. Ellenbeck's avatar L. Ellenbeck

Added database support coscine/issues#209

parent f017bcb8
using Coscine.Api.Project.ReturnObjects;
using Coscine.Api.Project.Models;
using Coscine.Api.Project.ReturnObjects;
using Coscine.ApiCommons;
using Coscine.ApiCommons.Utils;
using Coscine.Configuration;
using Coscine.Database.Model;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
......@@ -16,58 +20,118 @@ namespace Coscine.Api.Project.Controllers
{
private readonly IConfiguration _configuration;
private readonly JWTHandler _jwtHandler;
private readonly static HttpClient _client = new HttpClient();
private static readonly HttpClient _client = new HttpClient();
private readonly Authenticator _authenticator;
private readonly ResourceModel _resourceModel;
public DataSourceController()
{
_configuration = new ConsulConfiguration();
_configuration = Program.Configuration;
_jwtHandler = new JWTHandler(_configuration);
_authenticator = new Authenticator(this, _configuration);
_resourceModel = new ResourceModel();
}
[HttpGet("[controller]/{*path}")]
public async Task<IActionResult> Get(string path)
// inferring a ../ (urlencoded) can manipulate the url.
// However the constructed signature for s3 won't match and it will not be resolved.
// This may be a problem for other provider!
[HttpGet("[controller]/{resourceId}/{*path}")]
public async Task<IActionResult> Get(string resourceId, string path)
{
// inferring a ../ (urlencoded) can manipulate the url.
// However the constructed signature for s3 won't match and it will not be resolved.
// If the path is null, an empty string is added.
string url = $"http://localhost:7777/v1/resources/0/providers/rds/{path}";
var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", BuildAuthHeader());
if (!Guid.TryParse(resourceId, out Guid resouceGuid))
{
return BadRequest($"{resourceId} is not a guid.");
}
// Thread safe according to msdn and HttpCompletionOption sets it to get only headers first.
var response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
if (response.IsSuccessStatusCode)
Resource resource;
try
{
if (response.Content.Headers.Contains("Content-Disposition"))
{
return File(await response.Content.ReadAsStreamAsync(),
response.Content.Headers.GetValues("Content-Type").First());
}
else
resource = _resourceModel.GetById(resouceGuid);
if (resource == null)
{
var data = JObject.Parse(await response.Content.ReadAsStringAsync())["data"];
return Ok(new WaterbutlerObject(path, data));
return NotFound($"Could not find resource with id: {resourceId}");
}
}
else
catch (Exception)
{
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return NotFound($"Coukd not find object for: \"{path}\".");
}
else
if (response.StatusCode == System.Net.HttpStatusCode.Forbidden)
return NotFound($"Could not find resource with id: {resourceId}");
}
// Temporary
#if (!DEBUG)
var user = _authenticator.GetUserFromToken();
if (!_resourceModel.OwnsResource(user, resource))
{
return Forbid($"The user does not own the resource {resourceId}");
}
#endif
if (resource.Type == null)
{
ResourceTypeModel resourceTypeModel = new ResourceTypeModel();
resource.Type = resourceTypeModel.GetById(resource.TypeId);
}
string authHeader = null;
if (resource.Type.DisplayName.ToLower() == "rds")
{
authHeader = BuildRdsAuthHeader();
}
else if (resource.Type.DisplayName.ToLower() == "gitlab")
{
authHeader = BuildGitlabAuthHeader();
}
if (authHeader != null)
{
// If the path is null, an empty string is added.
string url = $"{_configuration.GetString("coscine/global/waterbutler_url")}{resource.Type.DisplayName.ToLower()}/{path}";
var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authHeader);
// Thread safe according to msdn and HttpCompletionOption sets it to get only headers first.
var response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
if (response.IsSuccessStatusCode)
{
return Forbid($"Not allowed to access the datasource.");
if (response.Content.Headers.Contains("Content-Disposition"))
{
return File(await response.Content.ReadAsStreamAsync(),
response.Content.Headers.GetValues("Content-Type").First());
}
else
{
var data = JObject.Parse(await response.Content.ReadAsStringAsync())["data"];
return Ok(new WaterbutlerObject(path, data));
}
}
else
{
return BadRequest($"Error in communication with waterbutler: {response.StatusCode}");
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return NotFound($"Could not find object for: \"{path}\".");
}
else
if (response.StatusCode == System.Net.HttpStatusCode.Forbidden)
{
return Forbid($"Not allowed to access the datasource.");
}
else
{
return BadRequest($"Error in communication with waterbutler: {response.StatusCode}");
}
}
}
else
{
return BadRequest($"No provider for: \"{resource.Type.DisplayName}\".");
}
}
private string BuildAuthHeader()
private string BuildRdsAuthHeader()
{
var auth = new Dictionary<string, object>();
......@@ -97,5 +161,10 @@ namespace Coscine.Api.Project.Controllers
return _jwtHandler.GenerateJwtToken(payload);
}
private string BuildGitlabAuthHeader()
{
return null;
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment