voidkitty/VoidCat/Controllers/UploadController.cs

183 lines
6.2 KiB
C#
Raw Normal View History

2022-02-26 23:32:19 +00:00
using Microsoft.AspNetCore.Mvc;
2022-01-28 10:32:00 +00:00
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
2022-01-25 23:39:51 +00:00
using Newtonsoft.Json;
2022-01-25 16:17:48 +00:00
using VoidCat.Model;
2022-02-21 09:39:59 +00:00
using VoidCat.Model.Paywall;
2022-02-16 16:33:00 +00:00
using VoidCat.Services.Abstractions;
2022-01-25 16:17:48 +00:00
namespace VoidCat.Controllers
{
[Route("upload")]
public class UploadController : Controller
{
2022-02-08 18:20:59 +00:00
private readonly IFileStore _storage;
2022-02-21 09:39:59 +00:00
private readonly IFileMetadataStore _metadata;
private readonly IPaywallStore _paywall;
2022-02-21 12:54:57 +00:00
private readonly IPaywallFactory _paywallFactory;
2022-02-27 13:54:25 +00:00
private readonly IFileInfoManager _fileInfo;
2022-01-25 16:17:48 +00:00
2022-02-21 12:54:57 +00:00
public UploadController(IFileStore storage, IFileMetadataStore metadata, IPaywallStore paywall,
2022-02-27 13:54:25 +00:00
IPaywallFactory paywallFactory, IFileInfoManager fileInfo)
2022-01-25 16:17:48 +00:00
{
2022-01-25 23:39:51 +00:00
_storage = storage;
2022-02-21 09:39:59 +00:00
_metadata = metadata;
_paywall = paywall;
2022-02-21 12:54:57 +00:00
_paywallFactory = paywallFactory;
2022-02-27 13:54:25 +00:00
_fileInfo = fileInfo;
2022-01-25 16:17:48 +00:00
}
[HttpPost]
2022-01-25 23:39:51 +00:00
[DisableRequestSizeLimit]
2022-01-28 10:32:00 +00:00
[DisableFormValueModelBinding]
2022-02-28 20:47:57 +00:00
public async Task<IActionResult> UploadFile([FromQuery] bool cli = false)
2022-01-25 16:17:48 +00:00
{
2022-02-10 22:22:34 +00:00
try
2022-02-03 23:06:39 +00:00
{
2022-02-24 23:05:33 +00:00
var uid = HttpContext.GetUserId();
2022-02-27 13:54:25 +00:00
var meta = new SecretVoidFileMeta()
2022-02-10 22:22:34 +00:00
{
2022-02-17 09:32:34 +00:00
MimeType = Request.Headers.GetHeader("V-Content-Type"),
2022-02-17 15:52:49 +00:00
Name = Request.Headers.GetHeader("V-Filename"),
Description = Request.Headers.GetHeader("V-Description"),
2022-02-24 23:05:33 +00:00
Digest = Request.Headers.GetHeader("V-Full-Digest"),
Uploader = uid
2022-02-10 22:22:34 +00:00
};
2022-02-17 09:32:34 +00:00
var digest = Request.Headers.GetHeader("V-Digest");
2022-02-28 20:47:57 +00:00
var vf = await _storage.Ingress(new(Request.Body, meta)
{
Hash = digest
}, HttpContext.RequestAborted);
if (cli)
{
var urlBuilder = new UriBuilder(Request.IsHttps ? "https" : "http", Request.Host.Host, Request.Host.Port ?? 80,
$"/d/{vf.Id.ToBase58()}");
return Content(urlBuilder.Uri.ToString(), "text/plain");
}
return Json(UploadResult.Success(vf));
2022-02-10 22:22:34 +00:00
}
catch (Exception ex)
{
2022-02-28 20:47:57 +00:00
return Json(UploadResult.Error(ex.Message));
2022-02-10 22:22:34 +00:00
}
}
[HttpPost]
[DisableRequestSizeLimit]
[DisableFormValueModelBinding]
[Route("{id}")]
public async Task<UploadResult> UploadFileAppend([FromRoute] string id)
{
try
{
var gid = id.FromBase58Guid();
2022-02-27 13:54:25 +00:00
var meta = await _metadata.Get<SecretVoidFileMeta>(gid);
if (meta == default) return UploadResult.Error("File not found");
2022-02-10 22:22:34 +00:00
2022-02-17 09:32:34 +00:00
var editSecret = Request.Headers.GetHeader("V-EditSecret");
var digest = Request.Headers.GetHeader("V-Digest");
2022-02-28 20:47:57 +00:00
var vf = await _storage.Ingress(new(Request.Body, meta)
2022-02-10 22:22:34 +00:00
{
2022-02-28 20:47:57 +00:00
Hash = digest,
2022-02-26 22:57:42 +00:00
EditSecret = editSecret?.FromBase58Guid() ?? Guid.Empty,
2022-02-10 22:22:34 +00:00
Id = gid
}, HttpContext.RequestAborted);
return UploadResult.Success(vf);
}
catch (Exception ex)
{
return UploadResult.Error(ex.Message);
}
2022-01-25 16:17:48 +00:00
}
2022-01-25 23:39:51 +00:00
[HttpGet]
[Route("{id}")]
2022-02-17 15:52:49 +00:00
public ValueTask<PublicVoidFile?> GetInfo([FromRoute] string id)
2022-01-25 16:17:48 +00:00
{
2022-02-27 13:54:25 +00:00
return _fileInfo.Get(id.FromBase58Guid());
2022-01-25 16:17:48 +00:00
}
2022-02-21 09:39:59 +00:00
[HttpGet]
[Route("{id}/paywall")]
2022-02-21 12:54:57 +00:00
public async ValueTask<PaywallOrder?> CreateOrder([FromRoute] string id)
2022-02-21 09:39:59 +00:00
{
2022-02-21 12:54:57 +00:00
var gid = id.FromBase58Guid();
2022-02-27 13:54:25 +00:00
var file = await _fileInfo.Get(gid);
2022-02-21 12:54:57 +00:00
var config = await _paywall.GetConfig(gid);
var provider = await _paywallFactory.CreateProvider(config!.Service);
return await provider.CreateOrder(file!);
2022-02-21 09:39:59 +00:00
}
2022-02-27 13:54:25 +00:00
2022-02-21 12:54:57 +00:00
[HttpGet]
[Route("{id}/paywall/{order:guid}")]
2022-02-27 13:54:25 +00:00
public async ValueTask<PaywallOrder?> GetOrderStatus([FromRoute] string id, [FromRoute] Guid order)
2022-02-21 12:54:57 +00:00
{
var gid = id.FromBase58Guid();
var config = await _paywall.GetConfig(gid);
var provider = await _paywallFactory.CreateProvider(config!.Service);
return await provider.GetOrderStatus(order);
}
2022-02-21 09:39:59 +00:00
[HttpPost]
[Route("{id}/paywall")]
public async Task<IActionResult> SetPaywallConfig([FromRoute] string id, [FromBody] SetPaywallConfigRequest req)
{
var gid = id.FromBase58Guid();
2022-02-27 13:54:25 +00:00
var meta = await _metadata.Get<SecretVoidFileMeta>(gid);
2022-02-21 09:39:59 +00:00
if (meta == default) return NotFound();
if (req.EditSecret != meta.EditSecret) return Unauthorized();
2022-02-21 12:54:57 +00:00
2022-02-21 09:39:59 +00:00
if (req.Strike != default)
{
await _paywall.SetConfig(gid, req.Strike!);
return Ok();
}
2022-02-21 14:32:13 +00:00
// if none set, set NoPaywallConfig
await _paywall.SetConfig(gid, new NoPaywallConfig());
return Ok();
2022-02-21 09:39:59 +00:00
}
2022-01-25 16:17:48 +00:00
}
2022-01-28 10:32:00 +00:00
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
var factories = context.ValueProviderFactories;
factories.RemoveType<FormValueProviderFactory>();
factories.RemoveType<FormFileValueProviderFactory>();
factories.RemoveType<JQueryFormValueProviderFactory>();
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
}
2022-02-10 22:22:34 +00:00
2022-02-17 15:52:49 +00:00
public record UploadResult(bool Ok, PrivateVoidFile? File, string? ErrorMessage)
2022-02-10 22:22:34 +00:00
{
2022-02-17 15:52:49 +00:00
public static UploadResult Success(PrivateVoidFile vf)
2022-02-10 22:22:34 +00:00
=> new(true, vf, null);
public static UploadResult Error(string message)
=> new(false, null, message);
}
2022-02-21 09:39:59 +00:00
public record SetPaywallConfigRequest
{
[JsonConverter(typeof(Base58GuidConverter))]
public Guid EditSecret { get; init; }
2022-02-21 12:54:57 +00:00
2022-02-21 09:39:59 +00:00
public StrikePaywallConfig? Strike { get; init; }
}
2022-02-27 13:54:25 +00:00
}