2022-02-26 14:22:22 +00:00
|
|
|
|
using Microsoft.AspNetCore.Cors;
|
|
|
|
|
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
|
|
|
|
|
{
|
2022-02-26 14:22:22 +00:00
|
|
|
|
[EnableCors(CorsPolicy.Upload)]
|
2022-01-25 16:17:48 +00:00
|
|
|
|
[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-01-25 16:17:48 +00:00
|
|
|
|
|
2022-02-21 12:54:57 +00:00
|
|
|
|
public UploadController(IFileStore storage, IFileMetadataStore metadata, IPaywallStore paywall,
|
|
|
|
|
IPaywallFactory paywallFactory)
|
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-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-10 22:22:34 +00:00
|
|
|
|
public async Task<UploadResult> UploadFile()
|
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-10 22:22:34 +00:00
|
|
|
|
var meta = new VoidFileMeta()
|
|
|
|
|
{
|
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-16 16:33:00 +00:00
|
|
|
|
var vf = await _storage.Ingress(new(Request.Body, meta, digest!), HttpContext.RequestAborted);
|
2022-02-10 22:22:34 +00:00
|
|
|
|
|
|
|
|
|
return UploadResult.Success(vf);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
return UploadResult.Error(ex.Message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[HttpPost]
|
|
|
|
|
[DisableRequestSizeLimit]
|
|
|
|
|
[DisableFormValueModelBinding]
|
|
|
|
|
[Route("{id}")]
|
|
|
|
|
public async Task<UploadResult> UploadFileAppend([FromRoute] string id)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var gid = id.FromBase58Guid();
|
|
|
|
|
var fileInfo = await _storage.Get(gid);
|
2022-02-16 16:33:00 +00:00
|
|
|
|
if (fileInfo == 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-10 22:22:34 +00:00
|
|
|
|
var vf = await _storage.Ingress(new(Request.Body, fileInfo.Metadata, digest!)
|
|
|
|
|
{
|
|
|
|
|
EditSecret = editSecret?.FromBase58Guid(),
|
|
|
|
|
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-01-25 23:39:51 +00:00
|
|
|
|
return _storage.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();
|
|
|
|
|
var file = await _storage.Get(gid);
|
|
|
|
|
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-21 12:54:57 +00:00
|
|
|
|
[HttpGet]
|
|
|
|
|
[Route("{id}/paywall/{order:guid}")]
|
|
|
|
|
public async ValueTask<PaywallOrder?> GetOrderStatus([FromRoute] string id, [FromRoute]Guid order)
|
|
|
|
|
{
|
|
|
|
|
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();
|
|
|
|
|
var meta = await _metadata.Get(gid);
|
|
|
|
|
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-16 16:33:00 +00:00
|
|
|
|
}
|