mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 22:44:29 +01:00
Add updated image upload support on Crowdfund plugin (#6254)
* Add updated image upload support on Crowdfund plugin * Refactor crowdfund image upload fix * update crowdfund url for greenfield api * Resolve integration test assertion * Remove superfluous and unused command argument * Fix missing validation error * Minor API controller update * Property and usage fixes * Fix test after merge --------- Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
This commit is contained in:
committed by
GitHub
parent
8f062f918b
commit
3a71c45a89
@@ -2,6 +2,7 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts;
|
||||
|
||||
@@ -14,4 +15,5 @@ public interface IFileService
|
||||
Task<string?> GetTemporaryFileUrl(Uri baseUri, string fileId, DateTimeOffset expiry,
|
||||
bool isDownload);
|
||||
Task RemoveFile(string fileId, string userId);
|
||||
Task<UploadImageResultModel> UploadImage(IFormFile file, string userId, long maxFileSizeInBytes = 1_000_000);
|
||||
}
|
||||
|
||||
15
BTCPayServer.Abstractions/Models/UploadImageResultModel.cs
Normal file
15
BTCPayServer.Abstractions/Models/UploadImageResultModel.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Models;
|
||||
|
||||
public class UploadImageResultModel
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public string Response { get; set; } = string.Empty;
|
||||
public IStoredFile? StoredFile { get; set; }
|
||||
}
|
||||
@@ -81,7 +81,7 @@ namespace BTCPayServer.Tests
|
||||
Assert.False(app.Archived);
|
||||
var crowdfundViewModel = await crowdfund.UpdateCrowdfund(app.Id).AssertViewModelAsync<UpdateCrowdfundViewModel>();
|
||||
crowdfundViewModel.Enabled = true;
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel, "save").Result);
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel).Result);
|
||||
Assert.IsType<ViewResult>(await crowdfund.ViewCrowdfund(app.Id));
|
||||
// Delete
|
||||
Assert.IsType<NotFoundResult>(apps2.DeleteApp(app.Id));
|
||||
@@ -121,7 +121,7 @@ namespace BTCPayServer.Tests
|
||||
crowdfundViewModel.Enabled = false;
|
||||
crowdfundViewModel.EndDate = null;
|
||||
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel, "save").Result);
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel).Result);
|
||||
|
||||
var anonAppPubsController = tester.PayTester.GetController<UICrowdfundController>();
|
||||
var crowdfundController = user.GetController<UICrowdfundController>();
|
||||
@@ -146,7 +146,7 @@ namespace BTCPayServer.Tests
|
||||
crowdfundViewModel.StartDate = DateTime.Today.AddDays(2);
|
||||
crowdfundViewModel.Enabled = true;
|
||||
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel, "save").Result);
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel).Result);
|
||||
Assert.IsType<NotFoundObjectResult>(await anonAppPubsController.ContributeToCrowdfund(app.Id, new ContributeToCrowdfund()
|
||||
{
|
||||
Amount = new decimal(0.01)
|
||||
@@ -157,7 +157,7 @@ namespace BTCPayServer.Tests
|
||||
crowdfundViewModel.EndDate = DateTime.Today.AddDays(-1);
|
||||
crowdfundViewModel.Enabled = true;
|
||||
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel, "save").Result);
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel).Result);
|
||||
Assert.IsType<NotFoundObjectResult>(await anonAppPubsController.ContributeToCrowdfund(app.Id, new ContributeToCrowdfund()
|
||||
{
|
||||
Amount = new decimal(0.01)
|
||||
@@ -170,7 +170,7 @@ namespace BTCPayServer.Tests
|
||||
crowdfundViewModel.TargetAmount = 1;
|
||||
crowdfundViewModel.TargetCurrency = "BTC";
|
||||
crowdfundViewModel.EnforceTargetAmount = true;
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel, "save").Result);
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel).Result);
|
||||
Assert.IsType<NotFoundObjectResult>(await anonAppPubsController.ContributeToCrowdfund(app.Id, new ContributeToCrowdfund()
|
||||
{
|
||||
Amount = new decimal(1.01)
|
||||
@@ -214,7 +214,7 @@ namespace BTCPayServer.Tests
|
||||
crowdfundViewModel.TargetCurrency = "BTC";
|
||||
crowdfundViewModel.UseAllStoreInvoices = true;
|
||||
crowdfundViewModel.EnforceTargetAmount = true;
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel, "save").Result);
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel).Result);
|
||||
|
||||
var publicApps = user.GetController<UICrowdfundController>();
|
||||
|
||||
@@ -268,7 +268,7 @@ namespace BTCPayServer.Tests
|
||||
Assert.Contains(AppService.GetAppInternalTag(app.Id), invoiceEntity.InternalTags);
|
||||
|
||||
crowdfundViewModel.UseAllStoreInvoices = false;
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel, "save").Result);
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel).Result);
|
||||
|
||||
TestLogs.LogInformation("Because UseAllStoreInvoices is false, let's make sure the invoice is not tagged");
|
||||
invoice = await user.BitPay.CreateInvoiceAsync(new Invoice
|
||||
@@ -287,7 +287,7 @@ namespace BTCPayServer.Tests
|
||||
TestLogs.LogInformation("After turning setting a softcap, let's check that only actual payments are counted");
|
||||
crowdfundViewModel.EnforceTargetAmount = false;
|
||||
crowdfundViewModel.UseAllStoreInvoices = true;
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel, "save").Result);
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel).Result);
|
||||
invoice = await user.BitPay.CreateInvoiceAsync(new Invoice
|
||||
{
|
||||
Buyer = new Buyer { email = "test@fwf.com" },
|
||||
@@ -356,7 +356,7 @@ namespace BTCPayServer.Tests
|
||||
crowdfundViewModel.FormId = lstForms[0].Id;
|
||||
crowdfundViewModel.TargetCurrency = "BTC";
|
||||
crowdfundViewModel.Enabled = true;
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel, "save").Result);
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel).Result);
|
||||
|
||||
var vm2 = await crowdfund.CrowdfundForm(app.Id, (decimal?)0.01).AssertViewModelAsync<FormViewModel>();
|
||||
var res = await crowdfund.CrowdfundFormSubmit(app.Id, (decimal)0.01, "", vm2);
|
||||
@@ -411,7 +411,7 @@ namespace BTCPayServer.Tests
|
||||
crowdfundViewModel.TargetCurrency = "BTC";
|
||||
crowdfundViewModel.Enabled = true;
|
||||
crowdfundViewModel.PerksTemplate = "[{\"id\": \"xxx\",\"title\": \"Perk 1\",\"priceType\": \"Fixed\",\"price\": \"0.001\",\"image\": \"\",\"description\": \"\",\"categories\": [],\"disabled\": false}]";
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel, "save").Result);
|
||||
Assert.IsType<RedirectToActionResult>(crowdfund.UpdateCrowdfund(app.Id, crowdfundViewModel).Result);
|
||||
|
||||
var vm2 = await crowdfund.CrowdfundForm(app.Id, (decimal?)0.01, "xxx").AssertViewModelAsync<FormViewModel>();
|
||||
var res = await crowdfund.CrowdfundFormSubmit(app.Id, (decimal)0.01, "xxx", vm2);
|
||||
|
||||
@@ -9,6 +9,7 @@ using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Plugins.Crowdfund;
|
||||
using BTCPayServer.Plugins.PointOfSale;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Apps;
|
||||
using BTCPayServer.Services.Rates;
|
||||
using BTCPayServer.Services.Stores;
|
||||
@@ -28,12 +29,14 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
public class GreenfieldAppsController : ControllerBase
|
||||
{
|
||||
private readonly AppService _appService;
|
||||
private readonly UriResolver _uriResolver;
|
||||
private readonly StoreRepository _storeRepository;
|
||||
private readonly CurrencyNameTable _currencies;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
|
||||
public GreenfieldAppsController(
|
||||
AppService appService,
|
||||
UriResolver uriResolver,
|
||||
StoreRepository storeRepository,
|
||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
CurrencyNameTable currencies,
|
||||
@@ -41,6 +44,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
)
|
||||
{
|
||||
_appService = appService;
|
||||
_uriResolver = uriResolver;
|
||||
_storeRepository = storeRepository;
|
||||
_currencies = currencies;
|
||||
_userManager = userManager;
|
||||
@@ -72,12 +76,12 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
Archived = request.Archived ?? false
|
||||
};
|
||||
|
||||
var settings = ToCrowdfundSettings(request, new CrowdfundSettings { Title = request.Title ?? request.AppName });
|
||||
var settings = ToCrowdfundSettings(request);
|
||||
appData.SetSettings(settings);
|
||||
|
||||
await _appService.UpdateOrCreateApp(appData);
|
||||
|
||||
return Ok(ToCrowdfundModel(appData));
|
||||
var model = await ToCrowdfundModel(appData);
|
||||
return Ok(model);
|
||||
}
|
||||
|
||||
[HttpPost("~/api/v1/stores/{storeId}/apps/pos")]
|
||||
@@ -208,7 +212,8 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
return AppNotFound();
|
||||
}
|
||||
|
||||
return Ok(ToCrowdfundModel(app));
|
||||
var model = await ToCrowdfundModel(app);
|
||||
return Ok(model);
|
||||
}
|
||||
|
||||
[HttpDelete("~/api/v1/apps/{appId}")]
|
||||
@@ -255,7 +260,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
return this.CreateAPIError(404, "app-not-found", "The app with specified ID was not found");
|
||||
}
|
||||
|
||||
private CrowdfundSettings ToCrowdfundSettings(CrowdfundAppRequest request, CrowdfundSettings settings)
|
||||
private CrowdfundSettings ToCrowdfundSettings(CrowdfundAppRequest request)
|
||||
{
|
||||
var parsedSounds = ValidateStringArray(request.Sounds);
|
||||
var parsedColors = ValidateStringArray(request.AnimationColors);
|
||||
@@ -271,7 +276,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
Description = request.Description?.Trim(),
|
||||
EndDate = request.EndDate?.UtcDateTime,
|
||||
TargetAmount = request.TargetAmount,
|
||||
MainImageUrl = request.MainImageUrl?.Trim(),
|
||||
MainImageUrl = request.MainImageUrl == null ? null : UnresolvedUri.Create(request.MainImageUrl),
|
||||
NotificationUrl = request.NotificationUrl?.Trim(),
|
||||
Tagline = request.Tagline?.Trim(),
|
||||
PerksTemplate = request.PerksTemplate is not null ? AppService.SerializeTemplate(AppService.Parse(request.PerksTemplate.Trim())) : null,
|
||||
@@ -411,7 +416,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
}
|
||||
}
|
||||
|
||||
private CrowdfundAppData ToCrowdfundModel(AppData appData)
|
||||
private async Task<CrowdfundAppData> ToCrowdfundModel(AppData appData)
|
||||
{
|
||||
var settings = appData.GetSettings<CrowdfundSettings>();
|
||||
Enum.TryParse<CrowdfundResetEvery>(settings.ResetEvery.ToString(), true, out var resetEvery);
|
||||
@@ -432,7 +437,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
Description = settings.Description,
|
||||
EndDate = settings.EndDate,
|
||||
TargetAmount = settings.TargetAmount,
|
||||
MainImageUrl = settings.MainImageUrl,
|
||||
MainImageUrl = settings.MainImageUrl == null ? null : await _uriResolver.Resolve(Request.GetAbsoluteRootUri(), settings.MainImageUrl),
|
||||
NotificationUrl = settings.NotificationUrl,
|
||||
Tagline = settings.Tagline,
|
||||
DisqusEnabled = settings.DisqusEnabled,
|
||||
|
||||
@@ -4,8 +4,10 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Abstractions.Form;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Controllers;
|
||||
@@ -44,6 +46,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
||||
EventAggregator eventAggregator,
|
||||
UriResolver uriResolver,
|
||||
StoreRepository storeRepository,
|
||||
IFileService fileService,
|
||||
UIInvoiceController invoiceController,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
FormDataService formDataService,
|
||||
@@ -53,6 +56,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
||||
_appService = appService;
|
||||
_userManager = userManager;
|
||||
_app = app;
|
||||
_fileService = fileService;
|
||||
_storeRepository = storeRepository;
|
||||
_eventAggregator = eventAggregator;
|
||||
_uriResolver = uriResolver;
|
||||
@@ -61,6 +65,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
||||
}
|
||||
|
||||
private readonly EventAggregator _eventAggregator;
|
||||
private readonly IFileService _fileService;
|
||||
private readonly UriResolver _uriResolver;
|
||||
private readonly CurrencyNameTable _currencies;
|
||||
private readonly StoreRepository _storeRepository;
|
||||
@@ -393,6 +398,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
||||
|
||||
var settings = app.GetSettings<CrowdfundSettings>();
|
||||
var resetEvery = Enum.GetName(typeof(CrowdfundResetEvery), settings.ResetEvery);
|
||||
|
||||
var vm = new UpdateCrowdfundViewModel
|
||||
{
|
||||
Title = settings.Title,
|
||||
@@ -405,8 +411,8 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
||||
EnforceTargetAmount = settings.EnforceTargetAmount,
|
||||
StartDate = settings.StartDate,
|
||||
TargetCurrency = settings.TargetCurrency,
|
||||
MainImageUrl = settings.MainImageUrl == null ? null : await _uriResolver.Resolve(Request.GetAbsoluteRootUri(), settings.MainImageUrl),
|
||||
Description = settings.Description,
|
||||
MainImageUrl = settings.MainImageUrl,
|
||||
EndDate = settings.EndDate,
|
||||
TargetAmount = settings.TargetAmount,
|
||||
NotificationUrl = settings.NotificationUrl,
|
||||
@@ -434,8 +440,13 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
||||
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
[HttpPost("{appId}/settings/crowdfund")]
|
||||
public async Task<IActionResult> UpdateCrowdfund(string appId, UpdateCrowdfundViewModel vm, string command)
|
||||
public async Task<IActionResult> UpdateCrowdfund(string appId, UpdateCrowdfundViewModel vm,
|
||||
[FromForm] bool RemoveLogoFile = false)
|
||||
{
|
||||
var userId = GetUserId();
|
||||
if (userId is null)
|
||||
return NotFound();
|
||||
|
||||
var app = GetCurrentApp();
|
||||
if (app == null)
|
||||
return NotFound();
|
||||
@@ -503,6 +514,16 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
||||
parsedAnimationColors = new CrowdfundSettings().AnimationColors;
|
||||
}
|
||||
|
||||
UploadImageResultModel imageUpload = null;
|
||||
if (vm.MainImageFile != null)
|
||||
{
|
||||
imageUpload = await _fileService.UploadImage(vm.MainImageFile, userId);
|
||||
if (!imageUpload.Success)
|
||||
{
|
||||
ModelState.AddModelError(nameof(vm.MainImageFile), imageUpload.Response);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View("Crowdfund/UpdateCrowdfund", vm);
|
||||
@@ -520,7 +541,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
||||
Description = vm.Description,
|
||||
EndDate = vm.EndDate?.ToUniversalTime(),
|
||||
TargetAmount = vm.TargetAmount,
|
||||
MainImageUrl = vm.MainImageUrl,
|
||||
MainImageUrl = app.GetSettings<CrowdfundSettings>()?.MainImageUrl,
|
||||
NotificationUrl = vm.NotificationUrl,
|
||||
Tagline = vm.Tagline,
|
||||
PerksTemplate = vm.PerksTemplate,
|
||||
@@ -538,6 +559,17 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
||||
FormId = vm.FormId
|
||||
};
|
||||
|
||||
if (imageUpload?.Success is true)
|
||||
{
|
||||
newSettings.MainImageUrl = new UnresolvedUri.FileIdUri(imageUpload.StoredFile.Id);
|
||||
}
|
||||
else if (RemoveLogoFile)
|
||||
{
|
||||
newSettings.MainImageUrl = null;
|
||||
vm.MainImageUrl = null;
|
||||
vm.MainImageFile = null;
|
||||
}
|
||||
|
||||
app.TagAllInvoices = vm.UseAllStoreInvoices;
|
||||
app.SetSettings(newSettings);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Abstractions.Services;
|
||||
using BTCPayServer.Client.Models;
|
||||
@@ -49,22 +50,28 @@ namespace BTCPayServer.Plugins.Crowdfund
|
||||
private readonly IOptions<BTCPayServerOptions> _options;
|
||||
private readonly DisplayFormatter _displayFormatter;
|
||||
private readonly CurrencyNameTable _currencyNameTable;
|
||||
private readonly UriResolver _uriResolver;
|
||||
private readonly InvoiceRepository _invoiceRepository;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly PrettyNameProvider _prettyNameProvider;
|
||||
public const string AppType = "Crowdfund";
|
||||
|
||||
public CrowdfundAppType(
|
||||
LinkGenerator linkGenerator,
|
||||
IOptions<BTCPayServerOptions> options,
|
||||
UriResolver uriResolver,
|
||||
InvoiceRepository invoiceRepository,
|
||||
PrettyNameProvider prettyNameProvider,
|
||||
DisplayFormatter displayFormatter,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
CurrencyNameTable currencyNameTable)
|
||||
{
|
||||
Description = Type = AppType;
|
||||
_linkGenerator = linkGenerator;
|
||||
_options = options;
|
||||
_uriResolver = uriResolver;
|
||||
_displayFormatter = displayFormatter;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_currencyNameTable = currencyNameTable;
|
||||
_invoiceRepository = invoiceRepository;
|
||||
_prettyNameProvider = prettyNameProvider;
|
||||
@@ -186,12 +193,11 @@ namespace BTCPayServer.Plugins.Crowdfund
|
||||
? _linkGenerator.GetPathByAction(nameof(UICrowdfundController.CrowdfundForm), "UICrowdfund",
|
||||
new { appId = appData.Id }, _options.Value.RootPath)
|
||||
: null;
|
||||
return new ViewCrowdfundViewModel
|
||||
var vm = new ViewCrowdfundViewModel
|
||||
{
|
||||
Title = settings.Title,
|
||||
Tagline = settings.Tagline,
|
||||
Description = settings.Description,
|
||||
MainImageUrl = settings.MainImageUrl,
|
||||
StoreName = store.StoreName,
|
||||
StoreId = appData.StoreDataId,
|
||||
AppId = appData.Id,
|
||||
@@ -230,6 +236,12 @@ namespace BTCPayServer.Plugins.Crowdfund
|
||||
CurrentAmount = currentPayments.TotalCurrency
|
||||
}
|
||||
};
|
||||
var httpContext = _httpContextAccessor.HttpContext;
|
||||
if (httpContext != null && settings.MainImageUrl != null)
|
||||
{
|
||||
vm.MainImageUrl = await _uriResolver.Resolve(httpContext.Request.GetAbsoluteRootUri(), settings.MainImageUrl);
|
||||
}
|
||||
return vm;
|
||||
}
|
||||
|
||||
private Dictionary<string, PaymentStat> GetPaymentStats(InvoiceStatistics stats)
|
||||
|
||||
@@ -4,6 +4,8 @@ using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using BTCPayServer.Services.Apps;
|
||||
using BTCPayServer.Validation;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Plugins.Crowdfund.Models
|
||||
{
|
||||
@@ -32,6 +34,10 @@ namespace BTCPayServer.Plugins.Crowdfund.Models
|
||||
[Display(Name = "Featured Image URL")]
|
||||
public string MainImageUrl { get; set; }
|
||||
|
||||
[Display(Name = "Featured Image URL")]
|
||||
[JsonIgnore]
|
||||
public IFormFile MainImageFile { get; set; }
|
||||
|
||||
[Display(Name = "Callback Notification URL")]
|
||||
[Uri]
|
||||
public string NotificationUrl { get; set; }
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using BTCPayServer.JsonConverters;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Services.Apps
|
||||
{
|
||||
@@ -27,7 +29,8 @@ namespace BTCPayServer.Services.Apps
|
||||
}
|
||||
|
||||
public bool EnforceTargetAmount { get; set; }
|
||||
public string MainImageUrl { get; set; }
|
||||
[JsonConverter(typeof(UnresolvedUriJsonConverter))]
|
||||
public UnresolvedUri MainImageUrl { get; set; }
|
||||
public string NotificationUrl { get; set; }
|
||||
public string Tagline { get; set; }
|
||||
public string PerksTemplate { get; set; }
|
||||
|
||||
@@ -6,10 +6,12 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Configuration;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Storage.Models;
|
||||
@@ -47,6 +49,44 @@ namespace BTCPayServer.Storage.Services
|
||||
return settings is not null;
|
||||
}
|
||||
|
||||
public async Task<UploadImageResultModel> UploadImage(IFormFile file, string userId, long maxFileSizeInBytes = 1_000_000)
|
||||
{
|
||||
var result = new UploadImageResultModel();
|
||||
|
||||
if (file.Length > maxFileSizeInBytes)
|
||||
{
|
||||
result.Success = false;
|
||||
result.Response = $"The uploaded image file should be less than {maxFileSizeInBytes / 1_000_000}MB";
|
||||
return result;
|
||||
}
|
||||
if (!file.ContentType.StartsWith("image/", StringComparison.InvariantCulture))
|
||||
{
|
||||
result.Success = false;
|
||||
result.Response = "The uploaded file needs to be an image (based on content type)";
|
||||
return result;
|
||||
}
|
||||
var formFile = await file.Bufferize();
|
||||
if (!FileTypeDetector.IsPicture(formFile.Buffer, formFile.FileName))
|
||||
{
|
||||
result.Success = false;
|
||||
result.Response = "The uploaded file needs to be an image (based on file content)";
|
||||
return result;
|
||||
}
|
||||
try
|
||||
{
|
||||
result.StoredFile = await AddFile(formFile, userId);
|
||||
result.Success = true;
|
||||
result.Response = "Image uploaded successfully";
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
result.Success = false;
|
||||
result.Response = $"Could not save image: {e.Message}";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<IStoredFile> AddFile(IFormFile file, string userId)
|
||||
{
|
||||
var settings = await _settingsRepository.GetSettingAsync<StorageSettings>();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@using System.Globalization
|
||||
@using BTCPayServer.Abstractions.Contracts
|
||||
@using BTCPayServer.Abstractions.Models
|
||||
@using BTCPayServer.Client
|
||||
@using BTCPayServer.TagHelpers
|
||||
@@ -6,11 +7,13 @@
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using BTCPayServer.Forms
|
||||
@inject FormDataService FormDataService
|
||||
@inject IFileService FileService
|
||||
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
|
||||
@model BTCPayServer.Plugins.Crowdfund.Models.UpdateCrowdfundViewModel
|
||||
@{
|
||||
ViewData.SetActivePage(AppsNavPages.Update, "Update Crowdfund", Model.AppId);
|
||||
Csp.UnsafeEval();
|
||||
var canUpload = await FileService.IsAvailable();
|
||||
var checkoutFormOptions = await FormDataService.GetSelect(Model.StoreId, Model.FormId);
|
||||
}
|
||||
|
||||
@@ -25,7 +28,7 @@
|
||||
<script src="~/crowdfund/admin.js" asp-append-version="true"></script>
|
||||
}
|
||||
|
||||
<form method="post" permissioned="@Policies.CanModifyStoreSettings">
|
||||
<form method="post" enctype="multipart/form-data" permissioned="@Policies.CanModifyStoreSettings">
|
||||
<div class="sticky-header">
|
||||
<h2 text-translate="true">@ViewData["Title"]</h2>
|
||||
<div>
|
||||
@@ -74,9 +77,31 @@
|
||||
<span asp-validation-for="Tagline" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="MainImageUrl" class="form-label"></label>
|
||||
<input asp-for="MainImageUrl" class="form-control" />
|
||||
<span asp-validation-for="MainImageUrl" class="text-danger"></span>
|
||||
<div class="d-flex align-items-center justify-content-between gap-2">
|
||||
<label asp-for="MainImageFile" class="form-label"></label>
|
||||
@if (!string.IsNullOrEmpty(Model.MainImageUrl))
|
||||
{
|
||||
<button type="submit" class="btn btn-link p-0 text-danger" name="RemoveLogoFile" value="true">
|
||||
<vc:icon symbol="cross" /> Remove
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@if (canUpload)
|
||||
{
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<input asp-for="MainImageFile" type="file" class="form-control flex-grow">
|
||||
@if (!string.IsNullOrEmpty(Model.MainImageUrl))
|
||||
{
|
||||
<img src="@Model.MainImageUrl" alt="Logo" style="height:2.1rem;max-width:10.5rem;" />
|
||||
}
|
||||
</div>
|
||||
<span asp-validation-for="MainImageFile" class="text-danger"></span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<input asp-for="MainImageFile" type="file" class="form-control" disabled>
|
||||
<div class="form-text">In order to upload an image, a <a asp-controller="UIServer" asp-action="Files">file storage</a> must be configured.</div>
|
||||
}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="d-flex align-items-center">
|
||||
|
||||
Reference in New Issue
Block a user