Skip to content

Commit

Permalink
Migrate file IDs to URLs
Browse files Browse the repository at this point in the history
  • Loading branch information
dennisreimann committed May 7, 2024
1 parent 4fbc904 commit d367ad0
Show file tree
Hide file tree
Showing 22 changed files with 196 additions and 203 deletions.
7 changes: 2 additions & 5 deletions BTCPayServer/Components/MainLogo/Default.cshtml
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
@using BTCPayServer.Services
@using BTCPayServer.Abstractions.Contracts
@inject ThemeSettings Theme
@inject IFileService FileService
@model BTCPayServer.Components.MainLogo.MainLogoViewModel

@if (!string.IsNullOrEmpty(Theme.LogoFileId))
@if (!string.IsNullOrEmpty(Theme.LogoUrl))
{
var logoSrc = await FileService.GetFileUrl(Context.Request.GetAbsoluteRootUri(), Theme.LogoFileId);
<img src="@logoSrc" alt="BTCPay Server" class="main-logo main-logo-custom @Model.CssClass" />
<img src="@Theme.LogoUrl" alt="BTCPay Server" class="main-logo main-logo-custom @Model.CssClass" />
}
else
{
Expand Down
7 changes: 2 additions & 5 deletions BTCPayServer/Components/StoreSelector/Default.cshtml
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
@using BTCPayServer.Abstractions.Contracts
@using BTCPayServer.Client
@using BTCPayServer.Components.MainLogo
@using BTCPayServer.Services
@using BTCPayServer.Views.Server
@using BTCPayServer.Views.Stores
@inject BTCPayServerEnvironment Env
@inject IFileService FileService
@model BTCPayServer.Components.StoreSelector.StoreSelectorViewModel
@functions {
@* ReSharper disable once CSharpWarnings::CS1998 *@
Expand Down Expand Up @@ -39,9 +36,9 @@ else
<div id="StoreSelector">
<div id="StoreSelectorDropdown" class="dropdown only-for-js">
<button id="StoreSelectorToggle" class="btn btn-secondary dropdown-toggle rounded-pill px-3 @(Model.CurrentStoreId == null ? "empty-state" : "")" type="button" data-bs-toggle="dropdown" aria-expanded="false">
@if (!string.IsNullOrEmpty(Model.CurrentStoreLogoFileId))
@if (!string.IsNullOrEmpty(Model.CurrentStoreLogoUrl))
{
<img class="logo" src="@(await FileService.GetFileUrl(Context.Request.GetAbsoluteRootUri(), Model.CurrentStoreLogoFileId))" alt="@Model.CurrentDisplayName" />
<img class="logo" src="@Model.CurrentStoreLogoUrl" alt="@Model.CurrentDisplayName" />
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion BTCPayServer/Components/StoreSelector/StoreSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public async Task<IViewComponentResult> InvokeAsync()
Options = options,
CurrentStoreId = currentStore?.Id,
CurrentDisplayName = currentStore?.StoreName,
CurrentStoreLogoFileId = blob?.LogoFileId,
CurrentStoreLogoUrl = blob?.LogoUrl,
ArchivedCount = archivedCount
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class StoreSelectorViewModel
{
public List<StoreSelectorOption> Options { get; set; }
public string CurrentStoreId { get; set; }
public string CurrentStoreLogoFileId { get; set; }
public string CurrentStoreLogoUrl { get; set; }
public string CurrentDisplayName { get; set; }
public int ArchivedCount { get; set; }
}
Expand Down
4 changes: 2 additions & 2 deletions BTCPayServer/Controllers/UIInvoiceController.UI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -978,9 +978,9 @@ string GetPaymentMethodImage(PaymentMethodId paymentMethodId)

if (storeBlob.PlaySoundOnPayment)
{
model.PaymentSoundUrl = string.IsNullOrEmpty(storeBlob.SoundFileId)
model.PaymentSoundUrl = string.IsNullOrEmpty(storeBlob.PaymentSoundUrl)
? string.Concat(Request.GetAbsoluteRootUri().ToString(), "checkout/payment.mp3")
: await _fileService.GetFileUrl(Request.GetAbsoluteRootUri(), storeBlob.SoundFileId);
: storeBlob.PaymentSoundUrl;
model.ErrorSoundUrl = string.Concat(Request.GetAbsoluteRootUri().ToString(), "checkout/error.mp3");
model.NfcReadSoundUrl = string.Concat(Request.GetAbsoluteRootUri().ToString(), "checkout/nfcread.mp3");
}
Expand Down
60 changes: 22 additions & 38 deletions BTCPayServer/Controllers/UIServerController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1025,9 +1025,8 @@ public async Task<IActionResult> Branding()
ContactUrl = server.ContactUrl,
CustomTheme = theme.CustomTheme,
CustomThemeExtension = theme.CustomThemeExtension,
CustomThemeCssUri = theme.CustomThemeCssUri,
CustomThemeFileId = theme.CustomThemeFileId,
LogoFileId = theme.LogoFileId
CustomThemeCssUrl = theme.CustomThemeCssUrl,
LogoUrl = theme.LogoUrl
};
return View(vm);
}
Expand All @@ -1046,8 +1045,8 @@ public async Task<IActionResult> Branding()
if (userId is null)
return NotFound();

vm.LogoFileId = theme.LogoFileId;
vm.CustomThemeFileId = theme.CustomThemeFileId;
vm.LogoUrl = theme.LogoUrl;
vm.CustomThemeCssUrl = theme.CustomThemeCssUrl;

if (server.ServerName != vm.ServerName)
{
Expand All @@ -1072,17 +1071,11 @@ public async Task<IActionResult> Branding()
{
if (vm.CustomThemeFile.ContentType.Equals("text/css", StringComparison.InvariantCulture))
{
// delete existing file
if (!string.IsNullOrEmpty(theme.CustomThemeFileId))
{
await _fileService.RemoveFile(theme.CustomThemeFileId, userId);
}

// add new file
try
{
var storedFile = await _fileService.AddFile(vm.CustomThemeFile, userId);
vm.CustomThemeFileId = theme.CustomThemeFileId = storedFile.Id;
vm.CustomThemeCssUrl = theme.CustomThemeCssUrl = await GetRelativeFilePath(storedFile.Id);
settingsChanged = true;
}
catch (Exception e)
Expand All @@ -1095,10 +1088,11 @@ public async Task<IActionResult> Branding()
ModelState.AddModelError(nameof(vm.CustomThemeFile), "The uploaded theme file needs to be a CSS file");
}
}
else if (RemoveCustomThemeFile && !string.IsNullOrEmpty(theme.CustomThemeFileId))
else if (RemoveCustomThemeFile && !string.IsNullOrEmpty(theme.CustomThemeCssUrl))
{
await _fileService.RemoveFile(theme.CustomThemeFileId, userId);
vm.CustomThemeFileId = theme.CustomThemeFileId = null;
vm.CustomThemeCssUrl = theme.CustomThemeCssUrl = null;
theme.CustomTheme = false;
theme.CustomThemeExtension = ThemeExtension.Custom;
settingsChanged = true;
}

Expand All @@ -1122,16 +1116,11 @@ public async Task<IActionResult> Branding()
else
{
vm.LogoFile = formFile;
// delete existing file
if (!string.IsNullOrEmpty(theme.LogoFileId))
{
await _fileService.RemoveFile(theme.LogoFileId, userId);
}
// add new file
try
{
var storedFile = await _fileService.AddFile(vm.LogoFile, userId);
vm.LogoFileId = theme.LogoFileId = storedFile.Id;
vm.LogoUrl = theme.LogoUrl = await GetRelativeFilePath(storedFile.Id);
settingsChanged = true;
}
catch (Exception e)
Expand All @@ -1141,29 +1130,18 @@ public async Task<IActionResult> Branding()
}
}
}
else if (RemoveLogoFile && !string.IsNullOrEmpty(theme.LogoFileId))
{
await _fileService.RemoveFile(theme.LogoFileId, userId);
vm.LogoFileId = theme.LogoFileId = null;
settingsChanged = true;
}

if (vm.CustomTheme && !string.IsNullOrEmpty(vm.CustomThemeCssUri) && !Uri.IsWellFormedUriString(vm.CustomThemeCssUri, UriKind.RelativeOrAbsolute))
{
ModelState.AddModelError(nameof(theme.CustomThemeCssUri), "Please provide a non-empty theme URI");
}
else if (theme.CustomThemeCssUri != vm.CustomThemeCssUri)
else if (RemoveLogoFile && !string.IsNullOrEmpty(theme.LogoUrl))
{
theme.CustomThemeCssUri = vm.CustomThemeCssUri;
vm.LogoUrl = theme.LogoUrl = null;
settingsChanged = true;
}

if (theme.CustomThemeExtension != vm.CustomThemeExtension)
if (vm.CustomTheme && theme.CustomThemeExtension != vm.CustomThemeExtension)
{
// Require a custom theme to be defined in that case
if (string.IsNullOrEmpty(vm.CustomThemeCssUri) && string.IsNullOrEmpty(theme.CustomThemeFileId))
if (string.IsNullOrEmpty(vm.CustomThemeCssUrl) && string.IsNullOrEmpty(theme.CustomThemeCssUrl))
{
ModelState.AddModelError(nameof(vm.CustomThemeFile), "Please provide a custom theme");
ModelState.AddModelError(nameof(vm.CustomThemeCssUrl), "Please provide a custom theme");
}
else
{
Expand All @@ -1172,7 +1150,7 @@ public async Task<IActionResult> Branding()
}
}

if (theme.CustomTheme != vm.CustomTheme)
if (theme.CustomTheme != vm.CustomTheme && !RemoveCustomThemeFile)
{
theme.CustomTheme = vm.CustomTheme;
settingsChanged = true;
Expand All @@ -1182,6 +1160,7 @@ public async Task<IActionResult> Branding()
{
await _SettingsRepository.UpdateSetting(theme);
TempData[WellKnownTempData.SuccessMessage] = "Settings updated successfully";
return RedirectToAction(nameof(Branding));
}

return View(vm);
Expand Down Expand Up @@ -1325,5 +1304,10 @@ public async Task<IActionResult> LogsView(string? file = null, int offset = 0)

return View("Logs", vm);
}

private async Task<string?> GetRelativeFilePath(string fileId)
{
return (await _fileService.GetFileUrl(new Uri("/"), fileId))?.Replace("file://", "");
}
}
}
51 changes: 20 additions & 31 deletions BTCPayServer/Controllers/UIStoresController.Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using System.Threading.Tasks;
using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Abstractions.Models;
using BTCPayServer.Client;
using BTCPayServer.Data;
Expand Down Expand Up @@ -31,8 +32,8 @@ public IActionResult GeneralSettings()
Id = store.Id,
StoreName = store.StoreName,
StoreWebsite = store.StoreWebsite,
LogoFileId = storeBlob.LogoFileId,
CssFileId = storeBlob.CssFileId,
LogoUrl = storeBlob.LogoUrl,
CssUrl = storeBlob.CssUrl,
BrandColor = storeBlob.BrandColor,
NetworkFeeMode = storeBlob.NetworkFeeMode,
AnyoneCanCreateInvoice = storeBlob.AnyoneCanInvoice,
Expand Down Expand Up @@ -104,16 +105,11 @@ public IActionResult GeneralSettings()
else
{
model.LogoFile = formFile;
// delete existing file
if (!string.IsNullOrEmpty(blob.LogoFileId))
{
await _fileService.RemoveFile(blob.LogoFileId, userId);
}
// add new image
try
{
var storedFile = await _fileService.AddFile(model.LogoFile, userId);
blob.LogoFileId = storedFile.Id;
blob.LogoUrl = await GetRelativeFilePath(storedFile.Id);
}
catch (Exception e)
{
Expand All @@ -122,10 +118,9 @@ public IActionResult GeneralSettings()
}
}
}
else if (RemoveLogoFile && !string.IsNullOrEmpty(blob.LogoFileId))
else if (RemoveLogoFile && !string.IsNullOrEmpty(blob.LogoUrl))
{
await _fileService.RemoveFile(blob.LogoFileId, userId);
blob.LogoFileId = null;
blob.LogoUrl = null;
needUpdate = true;
}

Expand All @@ -145,27 +140,21 @@ public IActionResult GeneralSettings()
}
else
{
// delete existing file
if (!string.IsNullOrEmpty(blob.CssFileId))
{
await _fileService.RemoveFile(blob.CssFileId, userId);
}
// add new file
try
{
var storedFile = await _fileService.AddFile(model.CssFile, userId);
blob.CssFileId = storedFile.Id;
blob.CssUrl = await GetRelativeFilePath(storedFile.Id);
}
catch (Exception e)
{
ModelState.AddModelError(nameof(model.CssFile), $"Could not save CSS file: {e.Message}");
}
}
}
else if (RemoveCssFile && !string.IsNullOrEmpty(blob.CssFileId))
else if (RemoveCssFile && !string.IsNullOrEmpty(blob.CssUrl))
{
await _fileService.RemoveFile(blob.CssFileId, userId);
blob.CssFileId = null;
blob.CssUrl = null;
needUpdate = true;
}

Expand Down Expand Up @@ -253,7 +242,9 @@ public IActionResult CheckoutAppearance()
vm.LightningAmountInSatoshi = storeBlob.LightningAmountInSatoshi;
vm.LazyPaymentMethods = storeBlob.LazyPaymentMethods;
vm.RedirectAutomatically = storeBlob.RedirectAutomatically;
vm.SoundFileId = storeBlob.SoundFileId;
vm.PaymentSoundUrl = string.IsNullOrEmpty(storeBlob.PaymentSoundUrl)
? string.Concat(Request.GetAbsoluteRootUri().ToString(), "checkout/payment.mp3")
: storeBlob.PaymentSoundUrl;
vm.HtmlTitle = storeBlob.HtmlTitle;
vm.SupportUrl = storeBlob.StoreSupportUrl;
vm.DisplayExpirationTimer = (int)storeBlob.DisplayExpirationTimer.TotalMinutes;
Expand Down Expand Up @@ -316,17 +307,11 @@ public async Task<IActionResult> CheckoutAppearance(CheckoutAppearanceViewModel
else
{
model.SoundFile = formFile;
// delete existing file
if (!string.IsNullOrEmpty(blob.SoundFileId))
{
await _fileService.RemoveFile(blob.SoundFileId, userId);
}

// add new file
try
{
var storedFile = await _fileService.AddFile(model.SoundFile, userId);
blob.SoundFileId = storedFile.Id;
blob.PaymentSoundUrl = await GetRelativeFilePath(storedFile.Id);
needUpdate = true;
}
catch (Exception e)
Expand All @@ -336,10 +321,9 @@ public async Task<IActionResult> CheckoutAppearance(CheckoutAppearanceViewModel
}
}
}
else if (RemoveSoundFile && !string.IsNullOrEmpty(blob.SoundFileId))
else if (RemoveSoundFile && !string.IsNullOrEmpty(blob.PaymentSoundUrl))
{
await _fileService.RemoveFile(blob.SoundFileId, userId);
blob.SoundFileId = null;
blob.PaymentSoundUrl = null;
needUpdate = true;
}

Expand Down Expand Up @@ -433,4 +417,9 @@ void SetCryptoCurrencies(CheckoutAppearanceViewModel vm, StoreData storeData)

return defaultChoice is null ? null : choices.FirstOrDefault(c => defaultChoice.ToString().Equals(c.Value, StringComparison.OrdinalIgnoreCase));
}

private async Task<string?> GetRelativeFilePath(string fileId)
{
return (await _fileService.GetFileUrl(new Uri("/"), fileId))?.Replace("file://", "");
}
}
13 changes: 10 additions & 3 deletions BTCPayServer/Data/StoreBlob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
using BTCPayServer.Payments;
using BTCPayServer.Rating;
using BTCPayServer.Services.Mails;
using BTCPayServer.Services.Rates;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

Expand Down Expand Up @@ -217,8 +215,17 @@ public RateRules GetDefaultRateRules(BTCPayNetworkProvider networkProvider)

public List<UIStoresController.StoreEmailRule> EmailRules { get; set; }
public string BrandColor { get; set; }

public string LogoUrl { get; set; }
public string CssUrl { get; set; }

// Leave these in here post-2.0, because we need them for the migration
[Obsolete("Use LogoUrl instead")]
public string LogoFileId { get; set; }
[Obsolete("Use CssUrl instead")]
public string CssFileId { get; set; }
[Obsolete("Use PaymentSoundUrl instead")]
public string SoundFileId { get; set; }

[DefaultValue(true)]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
Expand All @@ -236,7 +243,7 @@ public RateRules GetDefaultRateRules(BTCPayNetworkProvider networkProvider)
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public bool PlaySoundOnPayment { get; set; }

public string SoundFileId { get; set; }
public string PaymentSoundUrl { get; set; }

public IPaymentFilter GetExcludedPaymentMethods()
{
Expand Down

0 comments on commit d367ad0

Please sign in to comment.