mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-19 06:54:19 +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;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using BTCPayServer.Abstractions.Models;
|
||||||
|
|
||||||
namespace BTCPayServer.Abstractions.Contracts;
|
namespace BTCPayServer.Abstractions.Contracts;
|
||||||
|
|
||||||
@@ -14,4 +15,5 @@ public interface IFileService
|
|||||||
Task<string?> GetTemporaryFileUrl(Uri baseUri, string fileId, DateTimeOffset expiry,
|
Task<string?> GetTemporaryFileUrl(Uri baseUri, string fileId, DateTimeOffset expiry,
|
||||||
bool isDownload);
|
bool isDownload);
|
||||||
Task RemoveFile(string fileId, string userId);
|
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);
|
Assert.False(app.Archived);
|
||||||
var crowdfundViewModel = await crowdfund.UpdateCrowdfund(app.Id).AssertViewModelAsync<UpdateCrowdfundViewModel>();
|
var crowdfundViewModel = await crowdfund.UpdateCrowdfund(app.Id).AssertViewModelAsync<UpdateCrowdfundViewModel>();
|
||||||
crowdfundViewModel.Enabled = true;
|
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));
|
Assert.IsType<ViewResult>(await crowdfund.ViewCrowdfund(app.Id));
|
||||||
// Delete
|
// Delete
|
||||||
Assert.IsType<NotFoundResult>(apps2.DeleteApp(app.Id));
|
Assert.IsType<NotFoundResult>(apps2.DeleteApp(app.Id));
|
||||||
@@ -121,7 +121,7 @@ namespace BTCPayServer.Tests
|
|||||||
crowdfundViewModel.Enabled = false;
|
crowdfundViewModel.Enabled = false;
|
||||||
crowdfundViewModel.EndDate = null;
|
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 anonAppPubsController = tester.PayTester.GetController<UICrowdfundController>();
|
||||||
var crowdfundController = user.GetController<UICrowdfundController>();
|
var crowdfundController = user.GetController<UICrowdfundController>();
|
||||||
@@ -146,7 +146,7 @@ namespace BTCPayServer.Tests
|
|||||||
crowdfundViewModel.StartDate = DateTime.Today.AddDays(2);
|
crowdfundViewModel.StartDate = DateTime.Today.AddDays(2);
|
||||||
crowdfundViewModel.Enabled = true;
|
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()
|
Assert.IsType<NotFoundObjectResult>(await anonAppPubsController.ContributeToCrowdfund(app.Id, new ContributeToCrowdfund()
|
||||||
{
|
{
|
||||||
Amount = new decimal(0.01)
|
Amount = new decimal(0.01)
|
||||||
@@ -157,7 +157,7 @@ namespace BTCPayServer.Tests
|
|||||||
crowdfundViewModel.EndDate = DateTime.Today.AddDays(-1);
|
crowdfundViewModel.EndDate = DateTime.Today.AddDays(-1);
|
||||||
crowdfundViewModel.Enabled = true;
|
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()
|
Assert.IsType<NotFoundObjectResult>(await anonAppPubsController.ContributeToCrowdfund(app.Id, new ContributeToCrowdfund()
|
||||||
{
|
{
|
||||||
Amount = new decimal(0.01)
|
Amount = new decimal(0.01)
|
||||||
@@ -170,7 +170,7 @@ namespace BTCPayServer.Tests
|
|||||||
crowdfundViewModel.TargetAmount = 1;
|
crowdfundViewModel.TargetAmount = 1;
|
||||||
crowdfundViewModel.TargetCurrency = "BTC";
|
crowdfundViewModel.TargetCurrency = "BTC";
|
||||||
crowdfundViewModel.EnforceTargetAmount = true;
|
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()
|
Assert.IsType<NotFoundObjectResult>(await anonAppPubsController.ContributeToCrowdfund(app.Id, new ContributeToCrowdfund()
|
||||||
{
|
{
|
||||||
Amount = new decimal(1.01)
|
Amount = new decimal(1.01)
|
||||||
@@ -214,7 +214,7 @@ namespace BTCPayServer.Tests
|
|||||||
crowdfundViewModel.TargetCurrency = "BTC";
|
crowdfundViewModel.TargetCurrency = "BTC";
|
||||||
crowdfundViewModel.UseAllStoreInvoices = true;
|
crowdfundViewModel.UseAllStoreInvoices = true;
|
||||||
crowdfundViewModel.EnforceTargetAmount = 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>();
|
var publicApps = user.GetController<UICrowdfundController>();
|
||||||
|
|
||||||
@@ -268,7 +268,7 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Contains(AppService.GetAppInternalTag(app.Id), invoiceEntity.InternalTags);
|
Assert.Contains(AppService.GetAppInternalTag(app.Id), invoiceEntity.InternalTags);
|
||||||
|
|
||||||
crowdfundViewModel.UseAllStoreInvoices = false;
|
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");
|
TestLogs.LogInformation("Because UseAllStoreInvoices is false, let's make sure the invoice is not tagged");
|
||||||
invoice = await user.BitPay.CreateInvoiceAsync(new Invoice
|
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");
|
TestLogs.LogInformation("After turning setting a softcap, let's check that only actual payments are counted");
|
||||||
crowdfundViewModel.EnforceTargetAmount = false;
|
crowdfundViewModel.EnforceTargetAmount = false;
|
||||||
crowdfundViewModel.UseAllStoreInvoices = true;
|
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
|
invoice = await user.BitPay.CreateInvoiceAsync(new Invoice
|
||||||
{
|
{
|
||||||
Buyer = new Buyer { email = "test@fwf.com" },
|
Buyer = new Buyer { email = "test@fwf.com" },
|
||||||
@@ -356,7 +356,7 @@ namespace BTCPayServer.Tests
|
|||||||
crowdfundViewModel.FormId = lstForms[0].Id;
|
crowdfundViewModel.FormId = lstForms[0].Id;
|
||||||
crowdfundViewModel.TargetCurrency = "BTC";
|
crowdfundViewModel.TargetCurrency = "BTC";
|
||||||
crowdfundViewModel.Enabled = true;
|
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 vm2 = await crowdfund.CrowdfundForm(app.Id, (decimal?)0.01).AssertViewModelAsync<FormViewModel>();
|
||||||
var res = await crowdfund.CrowdfundFormSubmit(app.Id, (decimal)0.01, "", vm2);
|
var res = await crowdfund.CrowdfundFormSubmit(app.Id, (decimal)0.01, "", vm2);
|
||||||
@@ -411,7 +411,7 @@ namespace BTCPayServer.Tests
|
|||||||
crowdfundViewModel.TargetCurrency = "BTC";
|
crowdfundViewModel.TargetCurrency = "BTC";
|
||||||
crowdfundViewModel.Enabled = true;
|
crowdfundViewModel.Enabled = true;
|
||||||
crowdfundViewModel.PerksTemplate = "[{\"id\": \"xxx\",\"title\": \"Perk 1\",\"priceType\": \"Fixed\",\"price\": \"0.001\",\"image\": \"\",\"description\": \"\",\"categories\": [],\"disabled\": false}]";
|
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 vm2 = await crowdfund.CrowdfundForm(app.Id, (decimal?)0.01, "xxx").AssertViewModelAsync<FormViewModel>();
|
||||||
var res = await crowdfund.CrowdfundFormSubmit(app.Id, (decimal)0.01, "xxx", vm2);
|
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.Data;
|
||||||
using BTCPayServer.Plugins.Crowdfund;
|
using BTCPayServer.Plugins.Crowdfund;
|
||||||
using BTCPayServer.Plugins.PointOfSale;
|
using BTCPayServer.Plugins.PointOfSale;
|
||||||
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Apps;
|
using BTCPayServer.Services.Apps;
|
||||||
using BTCPayServer.Services.Rates;
|
using BTCPayServer.Services.Rates;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
@@ -28,12 +29,14 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
public class GreenfieldAppsController : ControllerBase
|
public class GreenfieldAppsController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly AppService _appService;
|
private readonly AppService _appService;
|
||||||
|
private readonly UriResolver _uriResolver;
|
||||||
private readonly StoreRepository _storeRepository;
|
private readonly StoreRepository _storeRepository;
|
||||||
private readonly CurrencyNameTable _currencies;
|
private readonly CurrencyNameTable _currencies;
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
|
|
||||||
public GreenfieldAppsController(
|
public GreenfieldAppsController(
|
||||||
AppService appService,
|
AppService appService,
|
||||||
|
UriResolver uriResolver,
|
||||||
StoreRepository storeRepository,
|
StoreRepository storeRepository,
|
||||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||||
CurrencyNameTable currencies,
|
CurrencyNameTable currencies,
|
||||||
@@ -41,6 +44,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
_appService = appService;
|
_appService = appService;
|
||||||
|
_uriResolver = uriResolver;
|
||||||
_storeRepository = storeRepository;
|
_storeRepository = storeRepository;
|
||||||
_currencies = currencies;
|
_currencies = currencies;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
@@ -72,12 +76,12 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
Archived = request.Archived ?? false
|
Archived = request.Archived ?? false
|
||||||
};
|
};
|
||||||
|
|
||||||
var settings = ToCrowdfundSettings(request, new CrowdfundSettings { Title = request.Title ?? request.AppName });
|
var settings = ToCrowdfundSettings(request);
|
||||||
appData.SetSettings(settings);
|
appData.SetSettings(settings);
|
||||||
|
|
||||||
await _appService.UpdateOrCreateApp(appData);
|
await _appService.UpdateOrCreateApp(appData);
|
||||||
|
var model = await ToCrowdfundModel(appData);
|
||||||
return Ok(ToCrowdfundModel(appData));
|
return Ok(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("~/api/v1/stores/{storeId}/apps/pos")]
|
[HttpPost("~/api/v1/stores/{storeId}/apps/pos")]
|
||||||
@@ -208,7 +212,8 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
return AppNotFound();
|
return AppNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(ToCrowdfundModel(app));
|
var model = await ToCrowdfundModel(app);
|
||||||
|
return Ok(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpDelete("~/api/v1/apps/{appId}")]
|
[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");
|
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 parsedSounds = ValidateStringArray(request.Sounds);
|
||||||
var parsedColors = ValidateStringArray(request.AnimationColors);
|
var parsedColors = ValidateStringArray(request.AnimationColors);
|
||||||
@@ -271,7 +276,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
Description = request.Description?.Trim(),
|
Description = request.Description?.Trim(),
|
||||||
EndDate = request.EndDate?.UtcDateTime,
|
EndDate = request.EndDate?.UtcDateTime,
|
||||||
TargetAmount = request.TargetAmount,
|
TargetAmount = request.TargetAmount,
|
||||||
MainImageUrl = request.MainImageUrl?.Trim(),
|
MainImageUrl = request.MainImageUrl == null ? null : UnresolvedUri.Create(request.MainImageUrl),
|
||||||
NotificationUrl = request.NotificationUrl?.Trim(),
|
NotificationUrl = request.NotificationUrl?.Trim(),
|
||||||
Tagline = request.Tagline?.Trim(),
|
Tagline = request.Tagline?.Trim(),
|
||||||
PerksTemplate = request.PerksTemplate is not null ? AppService.SerializeTemplate(AppService.Parse(request.PerksTemplate.Trim())) : null,
|
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>();
|
var settings = appData.GetSettings<CrowdfundSettings>();
|
||||||
Enum.TryParse<CrowdfundResetEvery>(settings.ResetEvery.ToString(), true, out var resetEvery);
|
Enum.TryParse<CrowdfundResetEvery>(settings.ResetEvery.ToString(), true, out var resetEvery);
|
||||||
@@ -432,7 +437,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
Description = settings.Description,
|
Description = settings.Description,
|
||||||
EndDate = settings.EndDate,
|
EndDate = settings.EndDate,
|
||||||
TargetAmount = settings.TargetAmount,
|
TargetAmount = settings.TargetAmount,
|
||||||
MainImageUrl = settings.MainImageUrl,
|
MainImageUrl = settings.MainImageUrl == null ? null : await _uriResolver.Resolve(Request.GetAbsoluteRootUri(), settings.MainImageUrl),
|
||||||
NotificationUrl = settings.NotificationUrl,
|
NotificationUrl = settings.NotificationUrl,
|
||||||
Tagline = settings.Tagline,
|
Tagline = settings.Tagline,
|
||||||
DisqusEnabled = settings.DisqusEnabled,
|
DisqusEnabled = settings.DisqusEnabled,
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
using BTCPayServer.Abstractions.Extensions;
|
||||||
using BTCPayServer.Abstractions.Form;
|
using BTCPayServer.Abstractions.Form;
|
||||||
|
using BTCPayServer.Abstractions.Models;
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Controllers;
|
using BTCPayServer.Controllers;
|
||||||
@@ -44,6 +46,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
|||||||
EventAggregator eventAggregator,
|
EventAggregator eventAggregator,
|
||||||
UriResolver uriResolver,
|
UriResolver uriResolver,
|
||||||
StoreRepository storeRepository,
|
StoreRepository storeRepository,
|
||||||
|
IFileService fileService,
|
||||||
UIInvoiceController invoiceController,
|
UIInvoiceController invoiceController,
|
||||||
UserManager<ApplicationUser> userManager,
|
UserManager<ApplicationUser> userManager,
|
||||||
FormDataService formDataService,
|
FormDataService formDataService,
|
||||||
@@ -53,6 +56,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
|||||||
_appService = appService;
|
_appService = appService;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_app = app;
|
_app = app;
|
||||||
|
_fileService = fileService;
|
||||||
_storeRepository = storeRepository;
|
_storeRepository = storeRepository;
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_uriResolver = uriResolver;
|
_uriResolver = uriResolver;
|
||||||
@@ -61,6 +65,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly EventAggregator _eventAggregator;
|
private readonly EventAggregator _eventAggregator;
|
||||||
|
private readonly IFileService _fileService;
|
||||||
private readonly UriResolver _uriResolver;
|
private readonly UriResolver _uriResolver;
|
||||||
private readonly CurrencyNameTable _currencies;
|
private readonly CurrencyNameTable _currencies;
|
||||||
private readonly StoreRepository _storeRepository;
|
private readonly StoreRepository _storeRepository;
|
||||||
@@ -393,6 +398,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
|||||||
|
|
||||||
var settings = app.GetSettings<CrowdfundSettings>();
|
var settings = app.GetSettings<CrowdfundSettings>();
|
||||||
var resetEvery = Enum.GetName(typeof(CrowdfundResetEvery), settings.ResetEvery);
|
var resetEvery = Enum.GetName(typeof(CrowdfundResetEvery), settings.ResetEvery);
|
||||||
|
|
||||||
var vm = new UpdateCrowdfundViewModel
|
var vm = new UpdateCrowdfundViewModel
|
||||||
{
|
{
|
||||||
Title = settings.Title,
|
Title = settings.Title,
|
||||||
@@ -405,8 +411,8 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
|||||||
EnforceTargetAmount = settings.EnforceTargetAmount,
|
EnforceTargetAmount = settings.EnforceTargetAmount,
|
||||||
StartDate = settings.StartDate,
|
StartDate = settings.StartDate,
|
||||||
TargetCurrency = settings.TargetCurrency,
|
TargetCurrency = settings.TargetCurrency,
|
||||||
|
MainImageUrl = settings.MainImageUrl == null ? null : await _uriResolver.Resolve(Request.GetAbsoluteRootUri(), settings.MainImageUrl),
|
||||||
Description = settings.Description,
|
Description = settings.Description,
|
||||||
MainImageUrl = settings.MainImageUrl,
|
|
||||||
EndDate = settings.EndDate,
|
EndDate = settings.EndDate,
|
||||||
TargetAmount = settings.TargetAmount,
|
TargetAmount = settings.TargetAmount,
|
||||||
NotificationUrl = settings.NotificationUrl,
|
NotificationUrl = settings.NotificationUrl,
|
||||||
@@ -434,8 +440,13 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
|||||||
|
|
||||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||||
[HttpPost("{appId}/settings/crowdfund")]
|
[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();
|
var app = GetCurrentApp();
|
||||||
if (app == null)
|
if (app == null)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
@@ -503,6 +514,16 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
|||||||
parsedAnimationColors = new CrowdfundSettings().AnimationColors;
|
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)
|
if (!ModelState.IsValid)
|
||||||
{
|
{
|
||||||
return View("Crowdfund/UpdateCrowdfund", vm);
|
return View("Crowdfund/UpdateCrowdfund", vm);
|
||||||
@@ -520,7 +541,7 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
|||||||
Description = vm.Description,
|
Description = vm.Description,
|
||||||
EndDate = vm.EndDate?.ToUniversalTime(),
|
EndDate = vm.EndDate?.ToUniversalTime(),
|
||||||
TargetAmount = vm.TargetAmount,
|
TargetAmount = vm.TargetAmount,
|
||||||
MainImageUrl = vm.MainImageUrl,
|
MainImageUrl = app.GetSettings<CrowdfundSettings>()?.MainImageUrl,
|
||||||
NotificationUrl = vm.NotificationUrl,
|
NotificationUrl = vm.NotificationUrl,
|
||||||
Tagline = vm.Tagline,
|
Tagline = vm.Tagline,
|
||||||
PerksTemplate = vm.PerksTemplate,
|
PerksTemplate = vm.PerksTemplate,
|
||||||
@@ -538,6 +559,17 @@ namespace BTCPayServer.Plugins.Crowdfund.Controllers
|
|||||||
FormId = vm.FormId
|
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.TagAllInvoices = vm.UseAllStoreInvoices;
|
||||||
app.SetSettings(newSettings);
|
app.SetSettings(newSettings);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
|
using BTCPayServer.Abstractions.Extensions;
|
||||||
using BTCPayServer.Abstractions.Models;
|
using BTCPayServer.Abstractions.Models;
|
||||||
using BTCPayServer.Abstractions.Services;
|
using BTCPayServer.Abstractions.Services;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
@@ -49,22 +50,28 @@ namespace BTCPayServer.Plugins.Crowdfund
|
|||||||
private readonly IOptions<BTCPayServerOptions> _options;
|
private readonly IOptions<BTCPayServerOptions> _options;
|
||||||
private readonly DisplayFormatter _displayFormatter;
|
private readonly DisplayFormatter _displayFormatter;
|
||||||
private readonly CurrencyNameTable _currencyNameTable;
|
private readonly CurrencyNameTable _currencyNameTable;
|
||||||
|
private readonly UriResolver _uriResolver;
|
||||||
private readonly InvoiceRepository _invoiceRepository;
|
private readonly InvoiceRepository _invoiceRepository;
|
||||||
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
private readonly PrettyNameProvider _prettyNameProvider;
|
private readonly PrettyNameProvider _prettyNameProvider;
|
||||||
public const string AppType = "Crowdfund";
|
public const string AppType = "Crowdfund";
|
||||||
|
|
||||||
public CrowdfundAppType(
|
public CrowdfundAppType(
|
||||||
LinkGenerator linkGenerator,
|
LinkGenerator linkGenerator,
|
||||||
IOptions<BTCPayServerOptions> options,
|
IOptions<BTCPayServerOptions> options,
|
||||||
|
UriResolver uriResolver,
|
||||||
InvoiceRepository invoiceRepository,
|
InvoiceRepository invoiceRepository,
|
||||||
PrettyNameProvider prettyNameProvider,
|
PrettyNameProvider prettyNameProvider,
|
||||||
DisplayFormatter displayFormatter,
|
DisplayFormatter displayFormatter,
|
||||||
|
IHttpContextAccessor httpContextAccessor,
|
||||||
CurrencyNameTable currencyNameTable)
|
CurrencyNameTable currencyNameTable)
|
||||||
{
|
{
|
||||||
Description = Type = AppType;
|
Description = Type = AppType;
|
||||||
_linkGenerator = linkGenerator;
|
_linkGenerator = linkGenerator;
|
||||||
_options = options;
|
_options = options;
|
||||||
|
_uriResolver = uriResolver;
|
||||||
_displayFormatter = displayFormatter;
|
_displayFormatter = displayFormatter;
|
||||||
|
_httpContextAccessor = httpContextAccessor;
|
||||||
_currencyNameTable = currencyNameTable;
|
_currencyNameTable = currencyNameTable;
|
||||||
_invoiceRepository = invoiceRepository;
|
_invoiceRepository = invoiceRepository;
|
||||||
_prettyNameProvider = prettyNameProvider;
|
_prettyNameProvider = prettyNameProvider;
|
||||||
@@ -186,12 +193,11 @@ namespace BTCPayServer.Plugins.Crowdfund
|
|||||||
? _linkGenerator.GetPathByAction(nameof(UICrowdfundController.CrowdfundForm), "UICrowdfund",
|
? _linkGenerator.GetPathByAction(nameof(UICrowdfundController.CrowdfundForm), "UICrowdfund",
|
||||||
new { appId = appData.Id }, _options.Value.RootPath)
|
new { appId = appData.Id }, _options.Value.RootPath)
|
||||||
: null;
|
: null;
|
||||||
return new ViewCrowdfundViewModel
|
var vm = new ViewCrowdfundViewModel
|
||||||
{
|
{
|
||||||
Title = settings.Title,
|
Title = settings.Title,
|
||||||
Tagline = settings.Tagline,
|
Tagline = settings.Tagline,
|
||||||
Description = settings.Description,
|
Description = settings.Description,
|
||||||
MainImageUrl = settings.MainImageUrl,
|
|
||||||
StoreName = store.StoreName,
|
StoreName = store.StoreName,
|
||||||
StoreId = appData.StoreDataId,
|
StoreId = appData.StoreDataId,
|
||||||
AppId = appData.Id,
|
AppId = appData.Id,
|
||||||
@@ -230,6 +236,12 @@ namespace BTCPayServer.Plugins.Crowdfund
|
|||||||
CurrentAmount = currentPayments.TotalCurrency
|
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)
|
private Dictionary<string, PaymentStat> GetPaymentStats(InvoiceStatistics stats)
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ using System.ComponentModel.DataAnnotations;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using BTCPayServer.Services.Apps;
|
using BTCPayServer.Services.Apps;
|
||||||
using BTCPayServer.Validation;
|
using BTCPayServer.Validation;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.Crowdfund.Models
|
namespace BTCPayServer.Plugins.Crowdfund.Models
|
||||||
{
|
{
|
||||||
@@ -32,6 +34,10 @@ namespace BTCPayServer.Plugins.Crowdfund.Models
|
|||||||
[Display(Name = "Featured Image URL")]
|
[Display(Name = "Featured Image URL")]
|
||||||
public string MainImageUrl { get; set; }
|
public string MainImageUrl { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "Featured Image URL")]
|
||||||
|
[JsonIgnore]
|
||||||
|
public IFormFile MainImageFile { get; set; }
|
||||||
|
|
||||||
[Display(Name = "Callback Notification URL")]
|
[Display(Name = "Callback Notification URL")]
|
||||||
[Uri]
|
[Uri]
|
||||||
public string NotificationUrl { get; set; }
|
public string NotificationUrl { get; set; }
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using BTCPayServer.JsonConverters;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace BTCPayServer.Services.Apps
|
namespace BTCPayServer.Services.Apps
|
||||||
{
|
{
|
||||||
@@ -27,7 +29,8 @@ namespace BTCPayServer.Services.Apps
|
|||||||
}
|
}
|
||||||
|
|
||||||
public bool EnforceTargetAmount { get; set; }
|
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 NotificationUrl { get; set; }
|
||||||
public string Tagline { get; set; }
|
public string Tagline { get; set; }
|
||||||
public string PerksTemplate { get; set; }
|
public string PerksTemplate { get; set; }
|
||||||
|
|||||||
@@ -6,10 +6,12 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
using BTCPayServer.Abstractions.Extensions;
|
||||||
|
using BTCPayServer.Abstractions.Models;
|
||||||
using BTCPayServer.Configuration;
|
using BTCPayServer.Configuration;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Storage.Models;
|
using BTCPayServer.Storage.Models;
|
||||||
@@ -47,6 +49,44 @@ namespace BTCPayServer.Storage.Services
|
|||||||
return settings is not null;
|
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)
|
public async Task<IStoredFile> AddFile(IFormFile file, string userId)
|
||||||
{
|
{
|
||||||
var settings = await _settingsRepository.GetSettingAsync<StorageSettings>();
|
var settings = await _settingsRepository.GetSettingAsync<StorageSettings>();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
@using System.Globalization
|
@using System.Globalization
|
||||||
|
@using BTCPayServer.Abstractions.Contracts
|
||||||
@using BTCPayServer.Abstractions.Models
|
@using BTCPayServer.Abstractions.Models
|
||||||
@using BTCPayServer.Client
|
@using BTCPayServer.Client
|
||||||
@using BTCPayServer.TagHelpers
|
@using BTCPayServer.TagHelpers
|
||||||
@@ -6,11 +7,13 @@
|
|||||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
@using BTCPayServer.Forms
|
@using BTCPayServer.Forms
|
||||||
@inject FormDataService FormDataService
|
@inject FormDataService FormDataService
|
||||||
|
@inject IFileService FileService
|
||||||
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
|
@inject BTCPayServer.Security.ContentSecurityPolicies Csp
|
||||||
@model BTCPayServer.Plugins.Crowdfund.Models.UpdateCrowdfundViewModel
|
@model BTCPayServer.Plugins.Crowdfund.Models.UpdateCrowdfundViewModel
|
||||||
@{
|
@{
|
||||||
ViewData.SetActivePage(AppsNavPages.Update, "Update Crowdfund", Model.AppId);
|
ViewData.SetActivePage(AppsNavPages.Update, "Update Crowdfund", Model.AppId);
|
||||||
Csp.UnsafeEval();
|
Csp.UnsafeEval();
|
||||||
|
var canUpload = await FileService.IsAvailable();
|
||||||
var checkoutFormOptions = await FormDataService.GetSelect(Model.StoreId, Model.FormId);
|
var checkoutFormOptions = await FormDataService.GetSelect(Model.StoreId, Model.FormId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,7 +28,7 @@
|
|||||||
<script src="~/crowdfund/admin.js" asp-append-version="true"></script>
|
<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">
|
<div class="sticky-header">
|
||||||
<h2 text-translate="true">@ViewData["Title"]</h2>
|
<h2 text-translate="true">@ViewData["Title"]</h2>
|
||||||
<div>
|
<div>
|
||||||
@@ -74,9 +77,31 @@
|
|||||||
<span asp-validation-for="Tagline" class="text-danger"></span>
|
<span asp-validation-for="Tagline" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="MainImageUrl" class="form-label"></label>
|
<div class="d-flex align-items-center justify-content-between gap-2">
|
||||||
<input asp-for="MainImageUrl" class="form-control" />
|
<label asp-for="MainImageFile" class="form-label"></label>
|
||||||
<span asp-validation-for="MainImageUrl" class="text-danger"></span>
|
@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>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
|
|||||||
Reference in New Issue
Block a user