Implemented upload and downloading in daemon, api server and frontend
This commit is contained in:
@@ -78,7 +78,7 @@ public class ServerFileSystemController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{serverId:int}/files/upload")]
|
[HttpGet("{serverId:int}/files/upload")]
|
||||||
public async Task<ServerFilesUploadResponse> Upload([FromRoute] int serverId, [FromQuery] string path)
|
public async Task<ServerFilesUploadResponse> Upload([FromRoute] int serverId)
|
||||||
{
|
{
|
||||||
var server = await GetServerById(serverId);
|
var server = await GetServerById(serverId);
|
||||||
|
|
||||||
@@ -88,9 +88,8 @@ public class ServerFileSystemController : Controller
|
|||||||
{
|
{
|
||||||
parameters.Add("type", "upload");
|
parameters.Add("type", "upload");
|
||||||
parameters.Add("serverId", server.Id);
|
parameters.Add("serverId", server.Id);
|
||||||
parameters.Add("path", path);
|
|
||||||
},
|
},
|
||||||
TimeSpan.FromMinutes(5)
|
TimeSpan.FromMinutes(1)
|
||||||
);
|
);
|
||||||
|
|
||||||
var url = "";
|
var url = "";
|
||||||
@@ -104,6 +103,34 @@ public class ServerFileSystemController : Controller
|
|||||||
UploadUrl = url
|
UploadUrl = url
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("{serverId:int}/files/download")]
|
||||||
|
public async Task<ServerFilesDownloadResponse> Download([FromRoute] int serverId, [FromQuery] string path)
|
||||||
|
{
|
||||||
|
var server = await GetServerById(serverId);
|
||||||
|
|
||||||
|
var accessToken = NodeService.CreateAccessToken(
|
||||||
|
server.Node,
|
||||||
|
parameters =>
|
||||||
|
{
|
||||||
|
parameters.Add("type", "download");
|
||||||
|
parameters.Add("path", path);
|
||||||
|
parameters.Add("serverId", server.Id);
|
||||||
|
},
|
||||||
|
TimeSpan.FromMinutes(1)
|
||||||
|
);
|
||||||
|
|
||||||
|
var url = "";
|
||||||
|
|
||||||
|
url += server.Node.UseSsl ? "https://" : "http://";
|
||||||
|
url += $"{server.Node.Fqdn}:{server.Node.HttpPort}/";
|
||||||
|
url += $"api/servers/download?token={accessToken}";
|
||||||
|
|
||||||
|
return new ServerFilesDownloadResponse()
|
||||||
|
{
|
||||||
|
DownloadUrl = url
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<Server> GetServerById(int serverId)
|
private async Task<Server> GetServerById(int serverId)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -73,6 +73,19 @@ public class ServerFileSystem
|
|||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task Read(string inputPath, Func<Stream, Task> onHandle)
|
||||||
|
{
|
||||||
|
var path = Normalize(inputPath);
|
||||||
|
|
||||||
|
FileSystem.OpenFile(path, stream =>
|
||||||
|
{
|
||||||
|
// No try catch here because the safe fs abstraction already handles every error occuring in the handle
|
||||||
|
onHandle.Invoke(stream).Wait();
|
||||||
|
});
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
private string Normalize(string path)
|
private string Normalize(string path)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using MoonCore.Exceptions;
|
||||||
|
using MoonlightServers.Daemon.Configuration;
|
||||||
|
using MoonlightServers.Daemon.Helpers;
|
||||||
|
using MoonlightServers.Daemon.Services;
|
||||||
|
|
||||||
|
namespace MoonlightServers.Daemon.Http.Controllers.Servers;
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/servers/download")]
|
||||||
|
public class DownloadController : Controller
|
||||||
|
{
|
||||||
|
private readonly AccessTokenHelper AccessTokenHelper;
|
||||||
|
private readonly AppConfiguration Configuration;
|
||||||
|
private readonly ServerService ServerService;
|
||||||
|
|
||||||
|
public DownloadController(
|
||||||
|
AccessTokenHelper accessTokenHelper,
|
||||||
|
ServerService serverService,
|
||||||
|
AppConfiguration configuration
|
||||||
|
)
|
||||||
|
{
|
||||||
|
AccessTokenHelper = accessTokenHelper;
|
||||||
|
ServerService = serverService;
|
||||||
|
Configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task Download([FromQuery] string token)
|
||||||
|
{
|
||||||
|
#region Token validation
|
||||||
|
|
||||||
|
if (!AccessTokenHelper.Process(token, out var claims))
|
||||||
|
throw new HttpApiException("Invalid access token provided", 401);
|
||||||
|
|
||||||
|
var typeClaim = claims.FirstOrDefault(x => x.Type == "type");
|
||||||
|
|
||||||
|
if (typeClaim == null || typeClaim.Value != "download")
|
||||||
|
throw new HttpApiException("Invalid access token provided: Missing or invalid type", 401);
|
||||||
|
|
||||||
|
var serverIdClaim = claims.FirstOrDefault(x => x.Type == "serverId");
|
||||||
|
|
||||||
|
if (serverIdClaim == null || !int.TryParse(serverIdClaim.Value, out var serverId))
|
||||||
|
throw new HttpApiException("Invalid access token provided: Missing or invalid server id", 401);
|
||||||
|
|
||||||
|
var pathClaim = claims.FirstOrDefault(x => x.Type == "path");
|
||||||
|
|
||||||
|
if(pathClaim == null || string.IsNullOrEmpty(pathClaim.Value))
|
||||||
|
throw new HttpApiException("Invalid access token provided: Missing or invalid path", 401);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
var server = ServerService.GetServer(serverId);
|
||||||
|
|
||||||
|
if (server == null)
|
||||||
|
throw new HttpApiException("No server with this id found", 404);
|
||||||
|
|
||||||
|
var path = pathClaim.Value;
|
||||||
|
|
||||||
|
await server.FileSystem.Read(path, async dataStream =>
|
||||||
|
{
|
||||||
|
await Results.File(dataStream).ExecuteAsync(HttpContext);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
|
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
|
||||||
<PackageReference Include="MoonCore" Version="1.8.4" />
|
<PackageReference Include="MoonCore" Version="1.8.4" />
|
||||||
<PackageReference Include="MoonCore.Extended" Version="1.3.0" />
|
<PackageReference Include="MoonCore.Extended" Version="1.3.0" />
|
||||||
<PackageReference Include="MoonCore.Unix" Version="1.0.2" />
|
<PackageReference Include="MoonCore.Unix" Version="1.0.3" />
|
||||||
<PackageReference Include="Stateless" Version="5.17.0" />
|
<PackageReference Include="Stateless" Version="5.17.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2"/>
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ public class ServerFileSystemProvider : IFileSystemProvider
|
|||||||
await FileSystemService.Mkdir(ServerId, path);
|
await FileSystemService.Mkdir(ServerId, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Stream> Read(string path)
|
public async Task<Stream> Read(string path)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return await FileSystemService.Download(ServerId, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ public class ServerFileSystemService
|
|||||||
public async Task Upload(int serverId, string path, Stream dataStream)
|
public async Task Upload(int serverId, string path, Stream dataStream)
|
||||||
{
|
{
|
||||||
var uploadSession = await ApiClient.GetJson<ServerFilesUploadResponse>(
|
var uploadSession = await ApiClient.GetJson<ServerFilesUploadResponse>(
|
||||||
$"api/client/servers/{serverId}/files/upload?path={path}"
|
$"api/client/servers/{serverId}/files/upload"
|
||||||
);
|
);
|
||||||
|
|
||||||
using var httpClient = new HttpClient();
|
using var httpClient = new HttpClient();
|
||||||
@@ -55,4 +55,15 @@ public class ServerFileSystemService
|
|||||||
|
|
||||||
await httpClient.PostAsync(uploadSession.UploadUrl, content);
|
await httpClient.PostAsync(uploadSession.UploadUrl, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Stream> Download(int serverId, string path)
|
||||||
|
{
|
||||||
|
var downloadSession = await ApiClient.GetJson<ServerFilesDownloadResponse>(
|
||||||
|
$"api/client/servers/{serverId}/files/download?path={path}"
|
||||||
|
);
|
||||||
|
|
||||||
|
using var httpClient = new HttpClient();
|
||||||
|
|
||||||
|
return await httpClient.GetStreamAsync(downloadSession.DownloadUrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace MoonlightServers.Shared.Http.Responses.Client.Servers.Files;
|
||||||
|
|
||||||
|
public class ServerFilesDownloadResponse
|
||||||
|
{
|
||||||
|
public string DownloadUrl { get; set; }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user