diff --git a/BTCPayServer.Data/ApplicationDbContext.cs b/BTCPayServer.Data/ApplicationDbContext.cs index 2c38cd7f8..7f9e9a4f9 100644 --- a/BTCPayServer.Data/ApplicationDbContext.cs +++ b/BTCPayServer.Data/ApplicationDbContext.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using System.Threading.Tasks; -using BTCPayServer.Data.Data; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; @@ -90,23 +89,23 @@ namespace BTCPayServer.Data // some of the data models don't have OnModelCreating for now, commenting them - ApplicationUser.OnModelCreating(builder); + ApplicationUser.OnModelCreating(builder, Database); AddressInvoiceData.OnModelCreating(builder); - APIKeyData.OnModelCreating(builder); + APIKeyData.OnModelCreating(builder, Database); AppData.OnModelCreating(builder); - CustodianAccountData.OnModelCreating(builder); + CustodianAccountData.OnModelCreating(builder, Database); //StoredFile.OnModelCreating(builder); InvoiceEventData.OnModelCreating(builder); InvoiceSearchData.OnModelCreating(builder); InvoiceWebhookDeliveryData.OnModelCreating(builder); - InvoiceData.OnModelCreating(builder); - NotificationData.OnModelCreating(builder); + InvoiceData.OnModelCreating(builder, Database); + NotificationData.OnModelCreating(builder, Database); //OffchainTransactionData.OnModelCreating(builder); BTCPayServer.Data.PairedSINData.OnModelCreating(builder); PairingCodeData.OnModelCreating(builder); //PayjoinLock.OnModelCreating(builder); - PaymentRequestData.OnModelCreating(builder); - PaymentData.OnModelCreating(builder); + PaymentRequestData.OnModelCreating(builder, Database); + PaymentData.OnModelCreating(builder, Database); PayoutData.OnModelCreating(builder); PendingInvoiceData.OnModelCreating(builder); //PlannedTransaction.OnModelCreating(builder); @@ -117,7 +116,7 @@ namespace BTCPayServer.Data StoreWebhookData.OnModelCreating(builder); StoreData.OnModelCreating(builder, Database); U2FDevice.OnModelCreating(builder); - Fido2Credential.OnModelCreating(builder); + Fido2Credential.OnModelCreating(builder, Database); BTCPayServer.Data.UserStore.OnModelCreating(builder); //WalletData.OnModelCreating(builder); WalletObjectData.OnModelCreating(builder, Database); @@ -125,14 +124,14 @@ namespace BTCPayServer.Data #pragma warning disable CS0612 // Type or member is obsolete WalletTransactionData.OnModelCreating(builder); #pragma warning restore CS0612 // Type or member is obsolete - WebhookDeliveryData.OnModelCreating(builder); - LightningAddressData.OnModelCreating(builder); - PayoutProcessorData.OnModelCreating(builder); - //WebhookData.OnModelCreating(builder); - FormData.OnModelCreating(builder, Database); + WebhookDeliveryData.OnModelCreating(builder, Database); + LightningAddressData.OnModelCreating(builder, Database); + PayoutProcessorData.OnModelCreating(builder, Database); + WebhookData.OnModelCreating(builder, Database); + FormData.OnModelCreating(builder, Database); - if (Database.IsSqlite() && !_designTime) + if (Database.IsSqlite() && !_designTime) { // SQLite does not have proper support for DateTimeOffset via Entity Framework Core, see the limitations // here: https://docs.microsoft.com/en-us/ef/core/providers/sqlite/limitations#query-limitations diff --git a/BTCPayServer.Data/Data/APIKeyData.cs b/BTCPayServer.Data/Data/APIKeyData.cs index 6a60f625a..e0de051fa 100644 --- a/BTCPayServer.Data/Data/APIKeyData.cs +++ b/BTCPayServer.Data/Data/APIKeyData.cs @@ -1,9 +1,11 @@ +using System; using System.ComponentModel.DataAnnotations; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; namespace BTCPayServer.Data { - public class APIKeyData + public class APIKeyData : IHasBlob { [MaxLength(50)] public string Id { get; set; } @@ -16,13 +18,15 @@ namespace BTCPayServer.Data public APIKeyType Type { get; set; } = APIKeyType.Legacy; + [Obsolete("Use Blob2 instead")] public byte[] Blob { get; set; } + public string Blob2 { get; set; } public StoreData StoreData { get; set; } public ApplicationUser User { get; set; } public string Label { get; set; } - internal static void OnModelCreating(ModelBuilder builder) + internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade) { builder.Entity() .HasOne(o => o.StoreData) @@ -36,6 +40,13 @@ namespace BTCPayServer.Data builder.Entity() .HasIndex(o => o.StoreId); + + if (databaseFacade.IsNpgsql()) + { + builder.Entity() + .Property(o => o.Blob2) + .HasColumnType("JSONB"); + } } } diff --git a/BTCPayServer.Data/Data/ApplicationUser.cs b/BTCPayServer.Data/Data/ApplicationUser.cs index 78df548a5..3a109ff4c 100644 --- a/BTCPayServer.Data/Data/ApplicationUser.cs +++ b/BTCPayServer.Data/Data/ApplicationUser.cs @@ -2,11 +2,13 @@ using System; using System.Collections.Generic; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Newtonsoft.Json.Linq; namespace BTCPayServer.Data { // Add profile data for application users by adding properties to the ApplicationUser class - public class ApplicationUser : IdentityUser + public class ApplicationUser : IdentityUser, IHasBlob { public bool RequiresEmailConfirmation { get; set; } public List StoredFiles { get; set; } @@ -20,15 +22,28 @@ namespace BTCPayServer.Data public List UserStores { get; set; } public List Fido2Credentials { get; set; } + [Obsolete("Use Blob2 instead")] public byte[] Blob { get; set; } + public string Blob2 { get; set; } public List> UserRoles { get; set; } - public static void OnModelCreating(ModelBuilder builder) + public static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade) { builder.Entity() .HasMany>(user => user.UserRoles) .WithOne().HasForeignKey(role => role.UserId); + if (databaseFacade.IsNpgsql()) + { + builder.Entity() + .Property(o => o.Blob2) + .HasColumnType("JSONB"); + } } } + + public class UserBlob + { + public bool ShowInvoiceStatusChangeHint { get; set; } + } } diff --git a/BTCPayServer.Data/Data/CustodianAccountData.cs b/BTCPayServer.Data/Data/CustodianAccountData.cs index 3743b0506..4c5235028 100644 --- a/BTCPayServer.Data/Data/CustodianAccountData.cs +++ b/BTCPayServer.Data/Data/CustodianAccountData.cs @@ -1,11 +1,13 @@ +using System; using System.ComponentModel.DataAnnotations; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace BTCPayServer.Data; -public class CustodianAccountData +public class CustodianAccountData : IHasBlob { [Required] [MaxLength(50)] @@ -24,19 +26,29 @@ public class CustodianAccountData public string Name { get; set; } [JsonIgnore] + [Obsolete("Use Blob2 instead")] public byte[] Blob { get; set; } + [JsonIgnore] + public string Blob2 { get; set; } [JsonIgnore] public StoreData StoreData { get; set; } - internal static void OnModelCreating(ModelBuilder builder) + internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade) { builder.Entity() .HasOne(o => o.StoreData) .WithMany(i => i.CustodianAccounts) .HasForeignKey(i => i.StoreId).OnDelete(DeleteBehavior.Cascade); - builder.Entity() + builder.Entity() .HasIndex(o => o.StoreId); + + if (databaseFacade.IsNpgsql()) + { + builder.Entity() + .Property(o => o.Blob2) + .HasColumnType("JSONB"); + } } } diff --git a/BTCPayServer.Data/Data/Fido2Credential.cs b/BTCPayServer.Data/Data/Fido2Credential.cs index 101b6f82e..6aeb5af26 100644 --- a/BTCPayServer.Data/Data/Fido2Credential.cs +++ b/BTCPayServer.Data/Data/Fido2Credential.cs @@ -2,10 +2,11 @@ using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; namespace BTCPayServer.Data { - public class Fido2Credential + public class Fido2Credential : IHasBlobUntyped { public string Name { get; set; } [DatabaseGenerated(DatabaseGeneratedOption.Identity)] @@ -14,6 +15,7 @@ namespace BTCPayServer.Data public string ApplicationUserId { get; set; } public byte[] Blob { get; set; } + public string Blob2 { get; set; } public CredentialType Type { get; set; } public enum CredentialType { @@ -22,12 +24,18 @@ namespace BTCPayServer.Data [Display(Name = "Lightning node (LNURL Auth)")] LNURLAuth } - public static void OnModelCreating(ModelBuilder builder) + public static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade) { builder.Entity() .HasOne(o => o.ApplicationUser) .WithMany(i => i.Fido2Credentials) .HasForeignKey(i => i.ApplicationUserId).OnDelete(DeleteBehavior.Cascade); + if (databaseFacade.IsNpgsql()) + { + builder.Entity() + .Property(o => o.Blob2) + .HasColumnType("JSONB"); + } } public ApplicationUser ApplicationUser { get; set; } diff --git a/BTCPayServer.Data/Data/FormData.cs b/BTCPayServer.Data/Data/FormData.cs index 4914ae2ab..6598e5ce6 100644 --- a/BTCPayServer.Data/Data/FormData.cs +++ b/BTCPayServer.Data/Data/FormData.cs @@ -1,8 +1,8 @@ -using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations.Schema; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -namespace BTCPayServer.Data.Data; +namespace BTCPayServer.Data; public class FormData { diff --git a/BTCPayServer.Data/Data/IHasBlob.cs b/BTCPayServer.Data/Data/IHasBlob.cs new file mode 100644 index 000000000..fdff25ed6 --- /dev/null +++ b/BTCPayServer.Data/Data/IHasBlob.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BTCPayServer.Data +{ + public interface IHasBlob + { + [Obsolete("Use Blob2 instead")] + byte[] Blob { get; set; } + string Blob2 { get; set; } + } + public interface IHasBlob + { + [Obsolete("Use Blob2 instead")] + byte[] Blob { get; set; } + string Blob2 { get; set; } + public Type Type { get; set; } + } + public interface IHasBlobUntyped + { + [Obsolete("Use Blob2 instead")] + byte[] Blob { get; set; } + string Blob2 { get; set; } + } +} diff --git a/BTCPayServer.Data/Data/InvoiceData.cs b/BTCPayServer.Data/Data/InvoiceData.cs index 8f4d8ff44..da99085e8 100644 --- a/BTCPayServer.Data/Data/InvoiceData.cs +++ b/BTCPayServer.Data/Data/InvoiceData.cs @@ -2,10 +2,11 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; namespace BTCPayServer.Data { - public class InvoiceData + public class InvoiceData : IHasBlobUntyped { public string Id { get; set; } @@ -16,7 +17,9 @@ namespace BTCPayServer.Data public List Payments { get; set; } public List Events { get; set; } + [Obsolete("Use Blob2 instead")] public byte[] Blob { get; set; } + public string Blob2 { get; set; } public string ItemCode { get; set; } public string OrderId { get; set; } public string Status { get; set; } @@ -32,7 +35,7 @@ namespace BTCPayServer.Data public RefundData CurrentRefund { get; set; } - internal static void OnModelCreating(ModelBuilder builder) + internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade) { builder.Entity() .HasOne(o => o.StoreData) @@ -42,6 +45,13 @@ namespace BTCPayServer.Data builder.Entity() .HasOne(o => o.CurrentRefund); builder.Entity().HasIndex(o => o.Created); + + if (databaseFacade.IsNpgsql()) + { + builder.Entity() + .Property(o => o.Blob2) + .HasColumnType("JSONB"); + } } } } diff --git a/BTCPayServer.Data/Data/LightingAddressData.cs b/BTCPayServer.Data/Data/LightingAddressData.cs index c14386a69..6ee9c5d56 100644 --- a/BTCPayServer.Data/Data/LightingAddressData.cs +++ b/BTCPayServer.Data/Data/LightingAddressData.cs @@ -1,17 +1,21 @@ +using System; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; namespace BTCPayServer.Data; -public class LightningAddressData +public class LightningAddressData : IHasBlob { public string Username { get; set; } public string StoreDataId { get; set; } + [Obsolete("Use Blob2 instead")] public byte[] Blob { get; set; } + public string Blob2 { get; set; } public StoreData Store { get; set; } - internal static void OnModelCreating(ModelBuilder builder) + internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade) { builder.Entity() .HasOne(o => o.Store) @@ -20,6 +24,12 @@ public class LightningAddressData .IsRequired() .OnDelete(DeleteBehavior.Cascade); builder.Entity().HasKey(o => o.Username); + if (databaseFacade.IsNpgsql()) + { + builder.Entity() + .Property(o => o.Blob2) + .HasColumnType("JSONB"); + } } } diff --git a/BTCPayServer.Data/Data/NotificationData.cs b/BTCPayServer.Data/Data/NotificationData.cs index aa9d496b4..d5b79ed2c 100644 --- a/BTCPayServer.Data/Data/NotificationData.cs +++ b/BTCPayServer.Data/Data/NotificationData.cs @@ -1,10 +1,12 @@ using System; using System.ComponentModel.DataAnnotations; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; namespace BTCPayServer.Data { - public class NotificationData + public class NotificationData : IHasBlobUntyped { [MaxLength(36)] public string Id { get; set; } @@ -17,14 +19,23 @@ namespace BTCPayServer.Data [Required] public string NotificationType { get; set; } public bool Seen { get; set; } + [Obsolete("Use Blob2 instead")] public byte[] Blob { get; set; } + public string Blob2 { get; set; } - internal static void OnModelCreating(ModelBuilder builder) - { + + internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade) + { builder.Entity() .HasOne(o => o.ApplicationUser) .WithMany(n => n.Notifications) .HasForeignKey(k => k.ApplicationUserId).OnDelete(DeleteBehavior.Cascade); + if (databaseFacade.IsNpgsql()) + { + builder.Entity() + .Property(o => o.Blob2) + .HasColumnType("JSONB"); + } } } } diff --git a/BTCPayServer.Data/Data/PaymentData.cs b/BTCPayServer.Data/Data/PaymentData.cs index 1376f8335..9c577e8d4 100644 --- a/BTCPayServer.Data/Data/PaymentData.cs +++ b/BTCPayServer.Data/Data/PaymentData.cs @@ -1,24 +1,34 @@ +using System; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; namespace BTCPayServer.Data { - public class PaymentData + public class PaymentData : IHasBlobUntyped { public string Id { get; set; } public string InvoiceDataId { get; set; } public InvoiceData InvoiceData { get; set; } - + [Obsolete("Use Blob2 instead")] public byte[] Blob { get; set; } + public string Blob2 { get; set; } + public string Type { get; set; } public bool Accounted { get; set; } - internal static void OnModelCreating(ModelBuilder builder) + internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade) { builder.Entity() .HasOne(o => o.InvoiceData) .WithMany(i => i.Payments).OnDelete(DeleteBehavior.Cascade); builder.Entity() .HasIndex(o => o.InvoiceDataId); + if (databaseFacade.IsNpgsql()) + { + builder.Entity() + .Property(o => o.Blob2) + .HasColumnType("JSONB"); + } } } } diff --git a/BTCPayServer.Data/Data/PaymentRequestData.cs b/BTCPayServer.Data/Data/PaymentRequestData.cs index 36a5182d2..cb96ced46 100644 --- a/BTCPayServer.Data/Data/PaymentRequestData.cs +++ b/BTCPayServer.Data/Data/PaymentRequestData.cs @@ -1,9 +1,10 @@ using System; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; namespace BTCPayServer.Data { - public class PaymentRequestData + public class PaymentRequestData : IHasBlobUntyped { public string Id { get; set; } public DateTimeOffset Created { get; set; } @@ -14,10 +15,12 @@ namespace BTCPayServer.Data public Client.Models.PaymentRequestData.PaymentRequestStatus Status { get; set; } + [Obsolete("Use Blob2 instead")] public byte[] Blob { get; set; } + public string Blob2 { get; set; } - internal static void OnModelCreating(ModelBuilder builder) + internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade) { builder.Entity() .HasOne(o => o.StoreData) @@ -28,6 +31,13 @@ namespace BTCPayServer.Data .HasDefaultValue(new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero)); builder.Entity() .HasIndex(o => o.Status); + + if (databaseFacade.IsNpgsql()) + { + builder.Entity() + .Property(o => o.Blob2) + .HasColumnType("JSONB"); + } } } } diff --git a/BTCPayServer.Data/Data/PayoutProcessorData.cs b/BTCPayServer.Data/Data/PayoutProcessorData.cs index 537d304a0..0bb8e591d 100644 --- a/BTCPayServer.Data/Data/PayoutProcessorData.cs +++ b/BTCPayServer.Data/Data/PayoutProcessorData.cs @@ -1,9 +1,15 @@ +using System; using System.ComponentModel.DataAnnotations.Schema; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; -namespace BTCPayServer.Data.Data; +namespace BTCPayServer.Data; -public class PayoutProcessorData +public class AutomatedPayoutBlob +{ + public TimeSpan Interval { get; set; } = TimeSpan.FromHours(1); +} +public class PayoutProcessorData : IHasBlobUntyped { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public string Id { get; set; } @@ -12,14 +18,22 @@ public class PayoutProcessorData public string PaymentMethod { get; set; } public string Processor { get; set; } + [Obsolete("Use Blob2 instead")] public byte[] Blob { get; set; } + public string Blob2 { get; set; } - internal static void OnModelCreating(ModelBuilder builder) + internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade) { - builder.Entity() .HasOne(o => o.Store) .WithMany(data => data.PayoutProcessors).OnDelete(DeleteBehavior.Cascade); + + if (databaseFacade.IsNpgsql()) + { + builder.Entity() + .Property(o => o.Blob2) + .HasColumnType("JSONB"); + } } public override string ToString() diff --git a/BTCPayServer.Data/Data/StoreData.cs b/BTCPayServer.Data/Data/StoreData.cs index 9746db5f7..3ad1dd22c 100644 --- a/BTCPayServer.Data/Data/StoreData.cs +++ b/BTCPayServer.Data/Data/StoreData.cs @@ -3,11 +3,10 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Text; using BTCPayServer.Client.Models; -using BTCPayServer.Data.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using PayoutProcessorData = BTCPayServer.Data.Data.PayoutProcessorData; +using PayoutProcessorData = BTCPayServer.Data.PayoutProcessorData; namespace BTCPayServer.Data { diff --git a/BTCPayServer.Data/Data/WebhookData.cs b/BTCPayServer.Data/Data/WebhookData.cs index d07be4987..c251cf4b8 100644 --- a/BTCPayServer.Data/Data/WebhookData.cs +++ b/BTCPayServer.Data/Data/WebhookData.cs @@ -1,15 +1,29 @@ +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; namespace BTCPayServer.Data { - public class WebhookData + public class WebhookData : IHasBlobUntyped { [Key] [MaxLength(25)] public string Id { get; set; } - [Required] + [Obsolete("Use Blob2 instead")] public byte[] Blob { get; set; } + public string Blob2 { get; set; } public List Deliveries { get; set; } + + internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade) + { + if (databaseFacade.IsNpgsql()) + { + builder.Entity() + .Property(o => o.Blob2) + .HasColumnType("JSONB"); + } + } } } diff --git a/BTCPayServer.Data/Data/WebhookDeliveryData.cs b/BTCPayServer.Data/Data/WebhookDeliveryData.cs index 61423b331..d6e7591ef 100644 --- a/BTCPayServer.Data/Data/WebhookDeliveryData.cs +++ b/BTCPayServer.Data/Data/WebhookDeliveryData.cs @@ -1,10 +1,11 @@ using System; using System.ComponentModel.DataAnnotations; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; namespace BTCPayServer.Data { - public class WebhookDeliveryData + public class WebhookDeliveryData : IHasBlobUntyped { [Key] [MaxLength(25)] @@ -16,17 +17,24 @@ namespace BTCPayServer.Data [Required] public DateTimeOffset Timestamp { get; set; } - - [Required] + [Obsolete("Use Blob2 instead")] public byte[] Blob { get; set; } + public string Blob2 { get; set; } - internal static void OnModelCreating(ModelBuilder builder) + internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade) { builder.Entity() .HasOne(o => o.Webhook) .WithMany(a => a.Deliveries).OnDelete(DeleteBehavior.Cascade); builder.Entity().HasIndex(o => o.WebhookId); + + if (databaseFacade.IsNpgsql()) + { + builder.Entity() + .Property(o => o.Blob2) + .HasColumnType("JSONB"); + } } } } diff --git a/BTCPayServer.Data/Migrations/20230130040047_blob2.cs b/BTCPayServer.Data/Migrations/20230130040047_blob2.cs new file mode 100644 index 000000000..09a22f98d --- /dev/null +++ b/BTCPayServer.Data/Migrations/20230130040047_blob2.cs @@ -0,0 +1,150 @@ +using System; +using BTCPayServer.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BTCPayServer.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20230130040047_blob2")] + public partial class blob2 : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + var type = migrationBuilder.IsNpgsql() ? "JSONB" : "TEXT"; + migrationBuilder.AddColumn( + name: "Blob2", + table: "Webhooks", + type: type, + nullable: true); + + migrationBuilder.AddColumn( + name: "Blob2", + table: "WebhookDeliveries", + type: type, + nullable: true); + + migrationBuilder.AddColumn( + name: "Blob2", + table: "PaymentRequests", + type: type, + nullable: true); + + migrationBuilder.AddColumn( + name: "Blob2", + table: "Notifications", + type: type, + nullable: true); + + migrationBuilder.AddColumn( + name: "Blob2", + table: "LightningAddresses", + type: type, + nullable: true); + + migrationBuilder.AddColumn( + name: "Blob2", + table: "Fido2Credentials", + type: type, + nullable: true); + + migrationBuilder.AddColumn( + name: "Blob2", + table: "AspNetUsers", + type: type, + nullable: true); + + migrationBuilder.AddColumn( + name: "Blob2", + table: "ApiKeys", + type: type, + nullable: true); + + migrationBuilder.AddColumn( + name: "Blob2", + table: "Invoices", + type: type, + nullable: true); + migrationBuilder.AddColumn( + name: "Blob2", + table: "Payments", + type: type, + nullable: true); + + migrationBuilder.AddColumn( + name: "Blob2", + table: "PayoutProcessors", + type: type, + nullable: true); + + migrationBuilder.AddColumn( + name: "Blob2", + table: "CustodianAccount", + type: type, + nullable: true); + + migrationBuilder.AddColumn( + name: "Type", + table: "Payments", + type: "TEXT", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Blob2", + table: "Webhooks"); + + migrationBuilder.DropColumn( + name: "Blob2", + table: "WebhookDeliveries"); + + migrationBuilder.DropColumn( + name: "Blob2", + table: "PaymentRequests"); + + migrationBuilder.DropColumn( + name: "Blob2", + table: "Notifications"); + + migrationBuilder.DropColumn( + name: "Blob2", + table: "LightningAddresses"); + + migrationBuilder.DropColumn( + name: "Blob2", + table: "Fido2Credentials"); + + migrationBuilder.DropColumn( + name: "Blob2", + table: "AspNetUsers"); + + migrationBuilder.DropColumn( + name: "Blob2", + table: "ApiKeys"); + + migrationBuilder.DropColumn( + name: "Blob2", + table: "Invoices"); + + migrationBuilder.DropColumn( + name: "Blob2", + table: "Payments"); + migrationBuilder.DropColumn( + name: "Blob2", + table: "PayoutProcessors"); + + migrationBuilder.DropColumn( + name: "Blob2", + table: "CustodianAccount"); + + migrationBuilder.DropColumn( + name: "Type", + table: "Payments"); + } + } +} diff --git a/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs b/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs index df9b6f693..eacf2cd06 100644 --- a/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -45,6 +45,9 @@ namespace BTCPayServer.Migrations b.Property("Blob") .HasColumnType("BLOB"); + b.Property("Blob2") + .HasColumnType("TEXT"); + b.Property("Label") .HasColumnType("TEXT"); @@ -109,6 +112,9 @@ namespace BTCPayServer.Migrations b.Property("Blob") .HasColumnType("BLOB"); + b.Property("Blob2") + .HasColumnType("TEXT"); + b.Property("ConcurrencyStamp") .IsConcurrencyToken() .HasColumnType("TEXT"); @@ -183,6 +189,9 @@ namespace BTCPayServer.Migrations b.Property("Blob") .HasColumnType("BLOB"); + b.Property("Blob2") + .HasColumnType("TEXT"); + b.Property("CustodianCode") .IsRequired() .HasMaxLength(50) @@ -205,7 +214,7 @@ namespace BTCPayServer.Migrations b.ToTable("CustodianAccount"); }); - modelBuilder.Entity("BTCPayServer.Data.Data.FormData", b => + modelBuilder.Entity("BTCPayServer.Data.FormData", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -230,7 +239,7 @@ namespace BTCPayServer.Migrations b.ToTable("Forms"); }); - modelBuilder.Entity("BTCPayServer.Data.Data.PayoutProcessorData", b => + modelBuilder.Entity("BTCPayServer.Data.PayoutProcessorData", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -267,6 +276,9 @@ namespace BTCPayServer.Migrations b.Property("Blob") .HasColumnType("BLOB"); + b.Property("Blob2") + .HasColumnType("TEXT"); + b.Property("Name") .HasColumnType("TEXT"); @@ -291,6 +303,9 @@ namespace BTCPayServer.Migrations b.Property("Blob") .HasColumnType("BLOB"); + b.Property("Blob2") + .HasColumnType("TEXT"); + b.Property("Created") .HasColumnType("TEXT"); @@ -401,6 +416,9 @@ namespace BTCPayServer.Migrations b.Property("Blob") .HasColumnType("BLOB"); + b.Property("Blob2") + .HasColumnType("TEXT"); + b.Property("StoreDataId") .IsRequired() .HasColumnType("TEXT"); @@ -426,6 +444,9 @@ namespace BTCPayServer.Migrations b.Property("Blob") .HasColumnType("BLOB"); + b.Property("Blob2") + .HasColumnType("TEXT"); + b.Property("Created") .HasColumnType("TEXT"); @@ -537,9 +558,15 @@ namespace BTCPayServer.Migrations b.Property("Blob") .HasColumnType("BLOB"); + b.Property("Blob2") + .HasColumnType("TEXT"); + b.Property("InvoiceDataId") .HasColumnType("TEXT"); + b.Property("Type") + .HasColumnType("TEXT"); + b.HasKey("Id"); b.HasIndex("InvoiceDataId"); @@ -558,6 +585,9 @@ namespace BTCPayServer.Migrations b.Property("Blob") .HasColumnType("BLOB"); + b.Property("Blob2") + .HasColumnType("TEXT"); + b.Property("Created") .ValueGeneratedOnAdd() .HasColumnType("TEXT") @@ -945,9 +975,11 @@ namespace BTCPayServer.Migrations .HasColumnType("TEXT"); b.Property("Blob") - .IsRequired() .HasColumnType("BLOB"); + b.Property("Blob2") + .HasColumnType("TEXT"); + b.HasKey("Id"); b.ToTable("Webhooks"); @@ -960,9 +992,11 @@ namespace BTCPayServer.Migrations .HasColumnType("TEXT"); b.Property("Blob") - .IsRequired() .HasColumnType("BLOB"); + b.Property("Blob2") + .HasColumnType("TEXT"); + b.Property("Timestamp") .HasColumnType("TEXT"); @@ -1154,7 +1188,7 @@ namespace BTCPayServer.Migrations b.Navigation("StoreData"); }); - modelBuilder.Entity("BTCPayServer.Data.Data.FormData", b => + modelBuilder.Entity("BTCPayServer.Data.FormData", b => { b.HasOne("BTCPayServer.Data.StoreData", "Store") .WithMany("Forms") @@ -1164,7 +1198,7 @@ namespace BTCPayServer.Migrations b.Navigation("Store"); }); - modelBuilder.Entity("BTCPayServer.Data.Data.PayoutProcessorData", b => + modelBuilder.Entity("BTCPayServer.Data.PayoutProcessorData", b => { b.HasOne("BTCPayServer.Data.StoreData", "Store") .WithMany("PayoutProcessors") diff --git a/BTCPayServer.Tests/GreenfieldAPITests.cs b/BTCPayServer.Tests/GreenfieldAPITests.cs index 0d1cf49c4..756c60713 100644 --- a/BTCPayServer.Tests/GreenfieldAPITests.cs +++ b/BTCPayServer.Tests/GreenfieldAPITests.cs @@ -1696,7 +1696,9 @@ namespace BTCPayServer.Tests var db = tester.PayTester.GetService(); using var ctx = db.CreateContext(); var dbInvoice = await ctx.Invoices.FindAsync(oldInvoice.Id); +#pragma warning disable CS0618 // Type or member is obsolete dbInvoice.Blob = ZipUtils.Zip(invoiceV1); +#pragma warning restore CS0618 // Type or member is obsolete await ctx.SaveChangesAsync(); var newInvoice = await AssertInvoiceMetadata(); @@ -1998,7 +2000,7 @@ namespace BTCPayServer.Tests //get var invoice = await viewOnly.GetInvoice(user.StoreId, newInvoice.Id); - Assert.Equal(newInvoice.Metadata, invoice.Metadata); + Assert.True(JObject.DeepEquals(newInvoice.Metadata, invoice.Metadata)); var paymentMethods = await viewOnly.GetInvoicePaymentMethods(user.StoreId, newInvoice.Id); Assert.Single(paymentMethods); var paymentMethod = paymentMethods.First(); diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldPayoutProcessorsController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldPayoutProcessorsController.cs index 0a2fb100d..d33be55d7 100644 --- a/BTCPayServer/Controllers/GreenField/GreenfieldPayoutProcessorsController.cs +++ b/BTCPayServer/Controllers/GreenField/GreenfieldPayoutProcessorsController.cs @@ -11,6 +11,7 @@ using BTCPayServer.Security; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using StoreData = BTCPayServer.Data.StoreData; +using PayoutProcessorData = BTCPayServer.Client.Models.PayoutProcessorData; namespace BTCPayServer.Controllers.Greenfield { diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldStoreAutomatedLightningPayoutProcessorsController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldStoreAutomatedLightningPayoutProcessorsController.cs index cfdf6ca3a..41a7634a6 100644 --- a/BTCPayServer/Controllers/GreenField/GreenfieldStoreAutomatedLightningPayoutProcessorsController.cs +++ b/BTCPayServer/Controllers/GreenField/GreenfieldStoreAutomatedLightningPayoutProcessorsController.cs @@ -4,15 +4,14 @@ using System.Threading.Tasks; using BTCPayServer.Abstractions.Constants; using BTCPayServer.Client; using BTCPayServer.Client.Models; -using BTCPayServer.Data.Data; +using BTCPayServer.Data; using BTCPayServer.Payments; using BTCPayServer.PayoutProcessors; using BTCPayServer.PayoutProcessors.Lightning; -using BTCPayServer.PayoutProcessors.Settings; using BTCPayServer.Services.Invoices; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using PayoutProcessorData = BTCPayServer.Data.Data.PayoutProcessorData; +using PayoutProcessorData = BTCPayServer.Data.PayoutProcessorData; namespace BTCPayServer.Controllers.Greenfield { @@ -55,7 +54,7 @@ namespace BTCPayServer.Controllers.Greenfield return new LightningAutomatedPayoutSettings() { PaymentMethod = data.PaymentMethod, - IntervalSeconds = InvoiceRepository.FromBytes(data.Blob).Interval + IntervalSeconds = data.HasTypedBlob().GetBlob()!.Interval }; } @@ -81,7 +80,7 @@ namespace BTCPayServer.Controllers.Greenfield })) .FirstOrDefault(); activeProcessor ??= new PayoutProcessorData(); - activeProcessor.Blob = InvoiceRepository.ToBytes(FromModel(request)); + activeProcessor.HasTypedBlob().SetBlob(FromModel(request)); activeProcessor.StoreId = storeId; activeProcessor.PaymentMethod = paymentMethod; activeProcessor.Processor = LightningAutomatedPayoutSenderFactory.ProcessorName; diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldStoreAutomatedOnChainPayoutProcessorsController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldStoreAutomatedOnChainPayoutProcessorsController.cs index ac0276ed8..05bab0313 100644 --- a/BTCPayServer/Controllers/GreenField/GreenfieldStoreAutomatedOnChainPayoutProcessorsController.cs +++ b/BTCPayServer/Controllers/GreenField/GreenfieldStoreAutomatedOnChainPayoutProcessorsController.cs @@ -4,15 +4,14 @@ using System.Threading.Tasks; using BTCPayServer.Abstractions.Constants; using BTCPayServer.Client; using BTCPayServer.Client.Models; -using BTCPayServer.Data.Data; +using BTCPayServer.Data; using BTCPayServer.Payments; using BTCPayServer.PayoutProcessors; using BTCPayServer.PayoutProcessors.OnChain; -using BTCPayServer.PayoutProcessors.Settings; using BTCPayServer.Services.Invoices; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using PayoutProcessorData = BTCPayServer.Data.Data.PayoutProcessorData; +using PayoutProcessorData = BTCPayServer.Data.PayoutProcessorData; namespace BTCPayServer.Controllers.Greenfield { @@ -87,7 +86,7 @@ namespace BTCPayServer.Controllers.Greenfield })) .FirstOrDefault(); activeProcessor ??= new PayoutProcessorData(); - activeProcessor.Blob = InvoiceRepository.ToBytes(FromModel(request)); + activeProcessor.HasTypedBlob().SetBlob(FromModel(request)); activeProcessor.StoreId = storeId; activeProcessor.PaymentMethod = paymentMethod; activeProcessor.Processor = OnChainAutomatedPayoutSenderFactory.ProcessorName; diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldStoreLightningAddressesController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldStoreLightningAddressesController.cs index 7df7b09da..bfc08acbe 100644 --- a/BTCPayServer/Controllers/GreenField/GreenfieldStoreLightningAddressesController.cs +++ b/BTCPayServer/Controllers/GreenField/GreenfieldStoreLightningAddressesController.cs @@ -26,7 +26,9 @@ namespace BTCPayServer.Controllers.Greenfield private LightningAddressData ToModel(BTCPayServer.Data.LightningAddressData data) { - var blob = data.Blob.GetBlob(); + var blob = data.GetBlob(); + if (blob is null) + return new LightningAddressData(); return new LightningAddressData() { Username = data.Username, Max = blob.Max, Min = blob.Min, CurrencyCode = blob.CurrencyCode @@ -79,12 +81,13 @@ namespace BTCPayServer.Controllers.Greenfield if (await _lightningAddressService.Set(new Data.LightningAddressData() { StoreDataId = storeId, - Username = username, - Blob = new LightningAddressDataBlob() - { - Max = data.Max, Min = data.Min, CurrencyCode = data.CurrencyCode - }.SerializeBlob() - })) + Username = username + }.SetBlob(new LightningAddressDataBlob() + { + Max = data.Max, + Min = data.Min, + CurrencyCode = data.CurrencyCode + }))) { return await GetStoreLightningAddress(storeId, username); } diff --git a/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs b/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs index 249e34ab7..0c412d181 100644 --- a/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs +++ b/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs @@ -34,6 +34,7 @@ using PullPaymentData = BTCPayServer.Client.Models.PullPaymentData; using StoreData = BTCPayServer.Client.Models.StoreData; using StoreWebhookData = BTCPayServer.Client.Models.StoreWebhookData; using WebhookDeliveryData = BTCPayServer.Client.Models.WebhookDeliveryData; +using PayoutProcessorData = BTCPayServer.Client.Models.PayoutProcessorData; namespace BTCPayServer.Controllers.Greenfield { diff --git a/BTCPayServer/Controllers/UILNURLController.cs b/BTCPayServer/Controllers/UILNURLController.cs index f95836a7a..f55bc7fc8 100644 --- a/BTCPayServer/Controllers/UILNURLController.cs +++ b/BTCPayServer/Controllers/UILNURLController.cs @@ -336,7 +336,7 @@ namespace BTCPayServer return NotFound("Unknown username"); } - var blob = lightningAddressSettings.Blob.GetBlob(); + var blob = lightningAddressSettings.GetBlob(); return await GetLNURL("BTC", lightningAddressSettings.StoreDataId, blob.CurrencyCode, blob.Min, blob.Max, () => (username, null, null, null, null, true)); } @@ -684,7 +684,7 @@ namespace BTCPayServer { Items = addresses.Select(s => { - var blob = s.Blob.GetBlob(); + var blob = s.GetBlob(); return new EditLightningAddressVM.EditLightningAddressItem { Max = blob.Max, @@ -722,14 +722,13 @@ namespace BTCPayServer if (await _lightningAddressService.Set(new LightningAddressData() { StoreDataId = storeId, - Username = vm.Add.Username, - Blob = new LightningAddressDataBlob() - { - Max = vm.Add.Max, - Min = vm.Add.Min, - CurrencyCode = vm.Add.CurrencyCode - }.SerializeBlob() - })) + Username = vm.Add.Username + }.SetBlob(new LightningAddressDataBlob() + { + Max = vm.Add.Max, + Min = vm.Add.Min, + CurrencyCode = vm.Add.CurrencyCode + }))) { TempData.SetStatusMessageModel(new StatusMessageModel { diff --git a/BTCPayServer/Controllers/UIManageController.cs b/BTCPayServer/Controllers/UIManageController.cs index 53d57fac0..7bffc8a74 100644 --- a/BTCPayServer/Controllers/UIManageController.cs +++ b/BTCPayServer/Controllers/UIManageController.cs @@ -107,10 +107,8 @@ namespace BTCPayServer.Controllers var blob = user.GetBlob(); blob.ShowInvoiceStatusChangeHint = false; - if (user.SetBlob(blob)) - { - await _userManager.UpdateAsync(user); - } + user.SetBlob(blob); + await _userManager.UpdateAsync(user); return RedirectToAction(nameof(Index)); } diff --git a/BTCPayServer/Data/APIKeyDataExtensions.cs b/BTCPayServer/Data/APIKeyDataExtensions.cs deleted file mode 100644 index 873fda305..000000000 --- a/BTCPayServer/Data/APIKeyDataExtensions.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Linq; -using NBXplorer; -using Newtonsoft.Json.Linq; - -namespace BTCPayServer.Data -{ - public static class APIKeyDataExtensions - { - public static APIKeyBlob GetBlob(this APIKeyData apiKeyData) - { - return GetBlob(apiKeyData.Blob); - } - - public static bool SetBlob(this APIKeyData apiKeyData, APIKeyBlob blob) - { - var newBlob = SerializeBlob(blob); - if (apiKeyData?.Blob?.SequenceEqual(newBlob) is true) - return false; - apiKeyData.Blob = newBlob; - return true; - } - - public static T GetBlob(this byte[] data) - { - var result = data == null - ? default - : JObject.Parse(ZipUtils.Unzip(data)).ToObject(); - return result; - } - - public static byte[] SerializeBlob(this T blob) - { - var newBlob = new Serializer(null).ToString(blob); - return ZipUtils.Zip(newBlob); - } - } -} diff --git a/BTCPayServer/Data/CustodianAccountDataExtensions.cs b/BTCPayServer/Data/CustodianAccountDataExtensions.cs index d27b65a26..6d22c4d6a 100644 --- a/BTCPayServer/Data/CustodianAccountDataExtensions.cs +++ b/BTCPayServer/Data/CustodianAccountDataExtensions.cs @@ -1,3 +1,4 @@ +#nullable enable using BTCPayServer.Services.Invoices; using Newtonsoft.Json.Linq; @@ -7,19 +8,6 @@ public static class CustodianAccountDataExtensions { public static JObject GetBlob(this CustodianAccountData custodianAccountData) { - var result = custodianAccountData.Blob == null - ? new JObject() - : InvoiceRepository.FromBytes(custodianAccountData.Blob); - return result; - } - - public static bool SetBlob(this CustodianAccountData custodianAccountData, JObject blob) - { - var original = custodianAccountData.GetBlob(); - if (JToken.DeepEquals(original, blob)) - return false; - - custodianAccountData.Blob = blob is null ? null : InvoiceRepository.ToBytes(blob); - return true; + return ((IHasBlob)custodianAccountData).GetBlob() ?? new JObject(); } } diff --git a/BTCPayServer/Data/IHasBlobExtensions.cs b/BTCPayServer/Data/IHasBlobExtensions.cs new file mode 100644 index 000000000..532a159ba --- /dev/null +++ b/BTCPayServer/Data/IHasBlobExtensions.cs @@ -0,0 +1,92 @@ +#nullable enable +using System; +using System.Collections; +using System.Linq; +using System.Reflection.Metadata; +using NBXplorer; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace BTCPayServer.Data +{ + public static class IHasBlobExtensions + { + static readonly JsonSerializerSettings DefaultSerializer; + static IHasBlobExtensions() + { + DefaultSerializer = new JsonSerializerSettings() + { + ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(), + Formatting = Formatting.None + }; + NBitcoin.JsonConverters.Serializer.RegisterFrontConverters(DefaultSerializer); + } + class HasBlobWrapper : IHasBlob + { + IHasBlobUntyped data; + public HasBlobWrapper(IHasBlobUntyped data) + { + this.data = data; + } + [Obsolete("Use Blob2 instead")] + public byte[] Blob { get { return data.Blob; } set { data.Blob = value; } } + public string Blob2 { get { return data.Blob2; } set { data.Blob2 = value; } } + } + class HasBlobWrapper : IHasBlob + { + IHasBlobUntyped data; + private Type type; + + public HasBlobWrapper(IHasBlobUntyped data, Type type) + { + this.data = data; + this.type = type; + } + [Obsolete("Use Blob2 instead")] + public byte[] Blob { get => data.Blob; set => data.Blob = value; } + public string Blob2 { get => data.Blob2; set => data.Blob2 = value; } + public Type Type { get => type; set => type = value; } + } + + public static IHasBlob HasTypedBlob(this IHasBlobUntyped data) + { + return new HasBlobWrapper(data); + } + public static IHasBlob HasTypedBlob(this IHasBlobUntyped data, Type blobType) + { + return new HasBlobWrapper(data, blobType); + } + public static B? GetBlob(this IHasBlob data, JsonSerializerSettings? settings = null) + { + if (data.Blob2 is not null) + return JObject.Parse(data.Blob2).ToObject(JsonSerializer.CreateDefault(settings ?? DefaultSerializer)); +#pragma warning disable CS0618 // Type or member is obsolete + if (data.Blob is not null && data.Blob.Length != 0) + return JObject.Parse(ZipUtils.Unzip(data.Blob)).ToObject(); +#pragma warning restore CS0618 // Type or member is obsolete + return default; + } + + public static object? GetBlob(this IHasBlob data, JsonSerializerSettings? settings = null) + { + if (data.Blob2 is not null) + return JObject.Parse(data.Blob2).ToObject(data.Type, JsonSerializer.CreateDefault(settings ?? DefaultSerializer)); +#pragma warning disable CS0618 // Type or member is obsolete + if (data.Blob is not null && data.Blob.Length != 0) + return JObject.Parse(ZipUtils.Unzip(data.Blob)).ToObject(data.Type); +#pragma warning restore CS0618 // Type or member is obsolete + return default; + } + public static T SetBlob(this T data, B blob, JsonSerializerSettings? settings = null) where T : IHasBlob + { + if (blob is null) + data.Blob2 = null; + else + data.Blob2 = JObject.FromObject(blob, JsonSerializer.CreateDefault(settings ?? DefaultSerializer)).ToString(Formatting.None); +#pragma warning disable CS0618 // Type or member is obsolete + data.Blob = new byte[0]; +#pragma warning restore CS0618 // Type or member is obsolete + return data; + } + } +} diff --git a/BTCPayServer/Data/InvoiceDataExtensions.cs b/BTCPayServer/Data/InvoiceDataExtensions.cs index 8e5ea97c4..4042742b3 100644 --- a/BTCPayServer/Data/InvoiceDataExtensions.cs +++ b/BTCPayServer/Data/InvoiceDataExtensions.cs @@ -1,26 +1,44 @@ +using System.Reflection.Metadata; using BTCPayServer.Services.Invoices; +using Newtonsoft.Json; namespace BTCPayServer.Data { public static class InvoiceDataExtensions { + public static void SetBlob(this InvoiceData invoiceData, InvoiceEntity blob) + { + if (blob.Metadata is null) + blob.Metadata = new InvoiceMetadata(); + invoiceData.HasTypedBlob().SetBlob(blob); + } public static InvoiceEntity GetBlob(this InvoiceData invoiceData, BTCPayNetworkProvider networks) { - - var entity = InvoiceRepository.FromBytes(invoiceData.Blob); - entity.Networks = networks; - if (entity.Metadata is null) +#pragma warning disable CS0618 // Type or member is obsolete + if (invoiceData.Blob is not null && invoiceData.Blob.Length != 0) { - if (entity.Version < InvoiceEntity.GreenfieldInvoices_Version) + var entity = JsonConvert.DeserializeObject(ZipUtils.Unzip(invoiceData.Blob), InvoiceRepository.DefaultSerializerSettings); + entity.Networks = networks; + if (entity.Metadata is null) { - entity.MigrateLegacyInvoice(); - } - else - { - entity.Metadata = new InvoiceMetadata(); + if (entity.Version < InvoiceEntity.GreenfieldInvoices_Version) + { + entity.MigrateLegacyInvoice(); + } + else + { + entity.Metadata = new InvoiceMetadata(); + } } + return entity; } - return entity; + else + { + var entity = invoiceData.HasTypedBlob().GetBlob(); + entity.Networks = networks; + return entity; + } +#pragma warning restore CS0618 // Type or member is obsolete } public static InvoiceState GetInvoiceState(this InvoiceData invoiceData) { diff --git a/BTCPayServer/Data/PaymentDataExtensions.cs b/BTCPayServer/Data/PaymentDataExtensions.cs index fdfe01d92..618191723 100644 --- a/BTCPayServer/Data/PaymentDataExtensions.cs +++ b/BTCPayServer/Data/PaymentDataExtensions.cs @@ -1,4 +1,5 @@ using System.Runtime.InteropServices; +using BTCPayServer.Payments; using BTCPayServer.Services.Invoices; using Newtonsoft.Json.Linq; @@ -6,25 +7,48 @@ namespace BTCPayServer.Data { public static class PaymentDataExtensions { + public static void SetBlob(this PaymentData paymentData, PaymentEntity entity) + { + paymentData.Type = entity.GetPaymentMethodId().ToStringNormalized(); + paymentData.Blob2 = entity.Network.ToString(entity); + } public static PaymentEntity GetBlob(this PaymentData paymentData, BTCPayNetworkProvider networks) { - var unziped = ZipUtils.Unzip(paymentData.Blob); - var cryptoCode = "BTC"; - if (JObject.Parse(unziped).TryGetValue("cryptoCode", out var v) && v.Type == JTokenType.String) - cryptoCode = v.Value(); - var network = networks.GetNetwork(cryptoCode); - PaymentEntity paymentEntity = null; - if (network == null) +#pragma warning disable CS0618 // Type or member is obsolete + if (paymentData.Blob is not null && paymentData.Blob.Length != 0) { - return null; + var unziped = ZipUtils.Unzip(paymentData.Blob); + var cryptoCode = "BTC"; + if (JObject.Parse(unziped).TryGetValue("cryptoCode", out var v) && v.Type == JTokenType.String) + cryptoCode = v.Value(); + var network = networks.GetNetwork(cryptoCode); + PaymentEntity paymentEntity = null; + if (network == null) + { + return null; + } + else + { + paymentEntity = network.ToObject(unziped); + } + paymentEntity.Network = network; + paymentEntity.Accounted = paymentData.Accounted; + return paymentEntity; } - else +#pragma warning restore CS0618 // Type or member is obsolete + if (paymentData.Blob2 is not null) { - paymentEntity = network.ToObject(unziped); + if (!PaymentMethodId.TryParse(paymentData.Type, out var pmi)) + return null; + var network = networks.GetNetwork(pmi.CryptoCode); + if (network is null) + return null; + var entity = network.ToObject(paymentData.Blob2); + entity.Network = network; + entity.Accounted = paymentData.Accounted; + return entity; } - paymentEntity.Network = network; - paymentEntity.Accounted = paymentData.Accounted; - return paymentEntity; + return null; } } } diff --git a/BTCPayServer/Data/PaymentRequestDataExtensions.cs b/BTCPayServer/Data/PaymentRequestDataExtensions.cs index 14c2e3e17..d10db8bb7 100644 --- a/BTCPayServer/Data/PaymentRequestDataExtensions.cs +++ b/BTCPayServer/Data/PaymentRequestDataExtensions.cs @@ -9,13 +9,20 @@ namespace BTCPayServer.Data { public static PaymentRequestBaseData GetBlob(this PaymentRequestData paymentRequestData) { - var result = paymentRequestData.Blob == null - ? new PaymentRequestBaseData() - : ParseBlob(paymentRequestData.Blob); - return result; + if (paymentRequestData.Blob2 is not null) + { + return paymentRequestData.HasTypedBlob().GetBlob(); + } +#pragma warning disable CS0618 // Type or member is obsolete + else if (paymentRequestData.Blob is not null) + { + return ParseBlob(paymentRequestData.Blob); + } +#pragma warning restore CS0618 // Type or member is obsolete + return new PaymentRequestBaseData(); } - private static PaymentRequestBaseData ParseBlob(byte[] blob) + static PaymentRequestBaseData ParseBlob(byte[] blob) { var jobj = JObject.Parse(ZipUtils.Unzip(blob)); // Fixup some legacy payment requests @@ -24,14 +31,9 @@ namespace BTCPayServer.Data return jobj.ToObject(); } - public static bool SetBlob(this PaymentRequestData paymentRequestData, PaymentRequestBaseData blob) + public static void SetBlob(this PaymentRequestData paymentRequestData, PaymentRequestBaseData blob) { - var original = new Serializer(null).ToString(paymentRequestData.GetBlob()); - var newBlob = new Serializer(null).ToString(blob); - if (original == newBlob) - return false; - paymentRequestData.Blob = ZipUtils.Zip(newBlob); - return true; + paymentRequestData.HasTypedBlob().SetBlob(blob); } } } diff --git a/BTCPayServer/Data/WebhookDataExtensions.cs b/BTCPayServer/Data/WebhookDataExtensions.cs index f5010faf6..932be8208 100644 --- a/BTCPayServer/Data/WebhookDataExtensions.cs +++ b/BTCPayServer/Data/WebhookDataExtensions.cs @@ -48,19 +48,19 @@ namespace BTCPayServer.Data { public static WebhookBlob GetBlob(this WebhookData webhook) { - return JsonConvert.DeserializeObject(Encoding.UTF8.GetString(webhook.Blob)); + return webhook.HasTypedBlob().GetBlob(); } public static void SetBlob(this WebhookData webhook, WebhookBlob blob) { - webhook.Blob = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(blob)); + webhook.HasTypedBlob().SetBlob(blob); } public static WebhookDeliveryBlob GetBlob(this WebhookDeliveryData webhook) { - return JsonConvert.DeserializeObject(ZipUtils.Unzip(webhook.Blob), HostedServices.WebhookSender.DefaultSerializerSettings); + return webhook.HasTypedBlob().GetBlob(HostedServices.WebhookSender.DefaultSerializerSettings); } public static void SetBlob(this WebhookDeliveryData webhook, WebhookDeliveryBlob blob) { - webhook.Blob = ZipUtils.Zip(JsonConvert.SerializeObject(blob, Formatting.None, HostedServices.WebhookSender.DefaultSerializerSettings)); + webhook.HasTypedBlob().SetBlob(blob, HostedServices.WebhookSender.DefaultSerializerSettings); } } } diff --git a/BTCPayServer/Extensions/UserExtensions.cs b/BTCPayServer/Extensions/UserExtensions.cs index 138abb983..847058a97 100644 --- a/BTCPayServer/Extensions/UserExtensions.cs +++ b/BTCPayServer/Extensions/UserExtensions.cs @@ -17,27 +17,5 @@ namespace BTCPayServer name = String.Empty; return new MimeKit.MailboxAddress(name, user.Email); } - public static UserBlob GetBlob(this ApplicationUser user) - { - var result = user.Blob == null - ? new UserBlob() - : JObject.Parse(ZipUtils.Unzip(user.Blob)).ToObject(); - return result; - } - public static bool SetBlob(this ApplicationUser user, UserBlob blob) - { - var newBytes = InvoiceRepository.ToBytes(blob); - if (user.Blob != null && newBytes.SequenceEqual(user.Blob)) - { - return false; - } - user.Blob = newBytes; - return true; - } - } - - public class UserBlob - { - public bool ShowInvoiceStatusChangeHint { get; set; } } } diff --git a/BTCPayServer/Fido2/FidoExtensions.cs b/BTCPayServer/Fido2/FidoExtensions.cs index 4a7a6a92b..ac0621a49 100644 --- a/BTCPayServer/Fido2/FidoExtensions.cs +++ b/BTCPayServer/Fido2/FidoExtensions.cs @@ -9,23 +9,17 @@ namespace BTCPayServer.Fido2 { public static Fido2CredentialBlob GetFido2Blob(this Fido2Credential credential) { - var result = credential.Blob == null - ? new Fido2CredentialBlob() - : JObject.Parse(ZipUtils.Unzip(credential.Blob)).ToObject(); - return result; + return credential.HasTypedBlob().GetBlob() ?? new Fido2CredentialBlob(); } - public static bool SetBlob(this Fido2Credential credential, Fido2CredentialBlob descriptor) + public static void SetBlob(this Fido2Credential credential, Fido2CredentialBlob descriptor) { - var original = new Serializer(null).ToString(credential.GetFido2Blob()); - var newBlob = new Serializer(null).ToString(descriptor); - if (original == newBlob) - return false; + var current = credential.GetFido2Blob(); + var a = JObject.FromObject(current); + var b = JObject.FromObject(descriptor); + if (JObject.DeepEquals(a, b)) + return; credential.Type = Fido2Credential.CredentialType.FIDO2; - credential.Blob = ZipUtils.Zip(newBlob); - return true; + credential.HasTypedBlob().SetBlob(descriptor); } - - - } } diff --git a/BTCPayServer/Forms/FormDataExtensions.cs b/BTCPayServer/Forms/FormDataExtensions.cs index 8496198a7..5fc6b48bb 100644 --- a/BTCPayServer/Forms/FormDataExtensions.cs +++ b/BTCPayServer/Forms/FormDataExtensions.cs @@ -1,5 +1,5 @@ -using BTCPayServer.Abstractions.Form; -using BTCPayServer.Data.Data; +using BTCPayServer.Abstractions.Form; +using BTCPayServer.Data; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using Newtonsoft.Json.Linq; diff --git a/BTCPayServer/Forms/FormDataService.cs b/BTCPayServer/Forms/FormDataService.cs index ab637873a..254a91923 100644 --- a/BTCPayServer/Forms/FormDataService.cs +++ b/BTCPayServer/Forms/FormDataService.cs @@ -9,7 +9,6 @@ using System.Threading.Tasks; using BTCPayServer.Abstractions.Form; using BTCPayServer.Client.Models; using BTCPayServer.Data; -using BTCPayServer.Data.Data; using BTCPayServer.Models; using BTCPayServer.Services.Stores; using Microsoft.AspNetCore.Http; diff --git a/BTCPayServer/Forms/UIFormsController.cs b/BTCPayServer/Forms/UIFormsController.cs index 1a3ad22a5..d9b29b138 100644 --- a/BTCPayServer/Forms/UIFormsController.cs +++ b/BTCPayServer/Forms/UIFormsController.cs @@ -11,7 +11,6 @@ using BTCPayServer.Client; using BTCPayServer.Client.Models; using BTCPayServer.Controllers; using BTCPayServer.Data; -using BTCPayServer.Data.Data; using BTCPayServer.Forms.Models; using BTCPayServer.Services.Stores; using Microsoft.AspNetCore.Authorization; diff --git a/BTCPayServer/HostedServices/WebhookSender.cs b/BTCPayServer/HostedServices/WebhookSender.cs index 8b3e92893..337ef1755 100644 --- a/BTCPayServer/HostedServices/WebhookSender.cs +++ b/BTCPayServer/HostedServices/WebhookSender.cs @@ -318,7 +318,7 @@ namespace BTCPayServer.HostedServices var sig = Encoders.Hex.EncodeData(hmac.ComputeHash(bytes)); content.Headers.Add("BTCPay-Sig", $"sha256={sig}"); request.Content = content; - var deliveryBlob = ctx.Delivery.Blob is null ? new WebhookDeliveryBlob() : ctx.Delivery.GetBlob(); + var deliveryBlob = ctx.Delivery.GetBlob() ?? new WebhookDeliveryBlob(); deliveryBlob.Request = bytes; try { diff --git a/BTCPayServer/Hosting/MigrationStartupTask.cs b/BTCPayServer/Hosting/MigrationStartupTask.cs index 107b0c6b6..c4fd616fc 100644 --- a/BTCPayServer/Hosting/MigrationStartupTask.cs +++ b/BTCPayServer/Hosting/MigrationStartupTask.cs @@ -358,14 +358,14 @@ namespace BTCPayServer.Hosting new LightningAddressData() { StoreDataId = storeMap.Key, - Username = storeitem, - Blob = new LightningAddressDataBlob() - { - Max = val.Max, - Min = val.Min, - CurrencyCode = val.CurrencyCode - }.SerializeBlob() - }, ctx); + Username = storeitem + } + .SetBlob(new LightningAddressDataBlob() + { + Max = val.Max, + Min = val.Min, + CurrencyCode = val.CurrencyCode + }), ctx); } } } diff --git a/BTCPayServer/PayoutProcessors/BaseAutomatedPayoutProcessor.cs b/BTCPayServer/PayoutProcessors/BaseAutomatedPayoutProcessor.cs index 1205c8ce5..e5410dc75 100644 --- a/BTCPayServer/PayoutProcessors/BaseAutomatedPayoutProcessor.cs +++ b/BTCPayServer/PayoutProcessors/BaseAutomatedPayoutProcessor.cs @@ -4,16 +4,14 @@ using System.Linq; using System.Threading.Tasks; using BTCPayServer.Client.Models; using BTCPayServer.Data; -using BTCPayServer.Data.Data; using BTCPayServer.HostedServices; using BTCPayServer.Payments; -using BTCPayServer.PayoutProcessors.Settings; using BTCPayServer.Services.Invoices; using BTCPayServer.Services.Stores; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using PayoutData = BTCPayServer.Data.PayoutData; -using PayoutProcessorData = BTCPayServer.Data.Data.PayoutProcessorData; +using PayoutProcessorData = BTCPayServer.Data.PayoutProcessorData; namespace BTCPayServer.PayoutProcessors; @@ -79,9 +77,8 @@ public abstract class BaseAutomatedPayoutProcessor : BaseAsyncService where T await Task.Delay(blob.Interval, CancellationToken); } - - public static T GetBlob(PayoutProcessorData data) + public static T GetBlob(PayoutProcessorData payoutProcesserSettings) { - return InvoiceRepository.FromBytes(data.Blob); + return payoutProcesserSettings.HasTypedBlob().GetBlob(); } } diff --git a/BTCPayServer/PayoutProcessors/IPayoutProcessorFactory.cs b/BTCPayServer/PayoutProcessors/IPayoutProcessorFactory.cs index cd234205b..dbbb2f719 100644 --- a/BTCPayServer/PayoutProcessors/IPayoutProcessorFactory.cs +++ b/BTCPayServer/PayoutProcessors/IPayoutProcessorFactory.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Threading.Tasks; -using BTCPayServer.Data.Data; +using BTCPayServer.Data; using BTCPayServer.Payments; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; diff --git a/BTCPayServer/PayoutProcessors/Lightning/LightningAutomatedPayoutProcessor.cs b/BTCPayServer/PayoutProcessors/Lightning/LightningAutomatedPayoutProcessor.cs index 0d0776378..fe9c00c6f 100644 --- a/BTCPayServer/PayoutProcessors/Lightning/LightningAutomatedPayoutProcessor.cs +++ b/BTCPayServer/PayoutProcessors/Lightning/LightningAutomatedPayoutProcessor.cs @@ -5,13 +5,11 @@ using System.Threading.Tasks; using BTCPayServer.Client.Models; using BTCPayServer.Configuration; using BTCPayServer.Data; -using BTCPayServer.Data.Data; using BTCPayServer.Data.Payouts.LightningLike; using BTCPayServer.HostedServices; using BTCPayServer.Lightning; using BTCPayServer.Payments; using BTCPayServer.Payments.Lightning; -using BTCPayServer.PayoutProcessors.Settings; using BTCPayServer.Services; using BTCPayServer.Services.Stores; using LNURL; @@ -19,7 +17,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using PayoutData = BTCPayServer.Data.PayoutData; -using PayoutProcessorData = BTCPayServer.Data.Data.PayoutProcessorData; +using PayoutProcessorData = BTCPayServer.Data.PayoutProcessorData; namespace BTCPayServer.PayoutProcessors.Lightning; diff --git a/BTCPayServer/PayoutProcessors/Lightning/LightningAutomatedPayoutSenderFactory.cs b/BTCPayServer/PayoutProcessors/Lightning/LightningAutomatedPayoutSenderFactory.cs index ccec4de37..244ba1bff 100644 --- a/BTCPayServer/PayoutProcessors/Lightning/LightningAutomatedPayoutSenderFactory.cs +++ b/BTCPayServer/PayoutProcessors/Lightning/LightningAutomatedPayoutSenderFactory.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using BTCPayServer.Data.Data; +using BTCPayServer.Data; using BTCPayServer.Payments; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; diff --git a/BTCPayServer/PayoutProcessors/Lightning/UILightningAutomatedPayoutProcessorsController.cs b/BTCPayServer/PayoutProcessors/Lightning/UILightningAutomatedPayoutProcessorsController.cs index cacf7ff92..7a62599d3 100644 --- a/BTCPayServer/PayoutProcessors/Lightning/UILightningAutomatedPayoutProcessorsController.cs +++ b/BTCPayServer/PayoutProcessors/Lightning/UILightningAutomatedPayoutProcessorsController.cs @@ -6,10 +6,9 @@ using BTCPayServer.Abstractions.Constants; using BTCPayServer.Abstractions.Extensions; using BTCPayServer.Abstractions.Models; using BTCPayServer.Client; -using BTCPayServer.Data.Data; +using BTCPayServer.Data; using BTCPayServer.Payments; using BTCPayServer.PayoutProcessors.OnChain; -using BTCPayServer.PayoutProcessors.Settings; using BTCPayServer.Services.Invoices; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -90,7 +89,7 @@ public class UILightningAutomatedPayoutProcessorsController : Controller })) .FirstOrDefault(); activeProcessor ??= new PayoutProcessorData(); - activeProcessor.Blob = InvoiceRepository.ToBytes(automatedTransferBlob.ToBlob()); + activeProcessor.HasTypedBlob().SetBlob(automatedTransferBlob.ToBlob()); activeProcessor.StoreId = storeId; activeProcessor.PaymentMethod = new PaymentMethodId(cryptoCode, LightningPaymentType.Instance).ToString(); activeProcessor.Processor = _lightningAutomatedPayoutSenderFactory.Processor; diff --git a/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutBlob.cs b/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutBlob.cs index fe73541c2..0cc7cfeb4 100644 --- a/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutBlob.cs +++ b/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutBlob.cs @@ -1,4 +1,4 @@ -using BTCPayServer.PayoutProcessors.Settings; +using BTCPayServer.Data; namespace BTCPayServer.PayoutProcessors.OnChain; diff --git a/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutProcessor.cs b/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutProcessor.cs index f5c6f103f..88577b020 100644 --- a/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutProcessor.cs +++ b/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutProcessor.cs @@ -5,11 +5,9 @@ using System.Threading; using System.Threading.Tasks; using BTCPayServer.Client.Models; using BTCPayServer.Data; -using BTCPayServer.Data.Data; using BTCPayServer.Events; using BTCPayServer.HostedServices; using BTCPayServer.Payments; -using BTCPayServer.PayoutProcessors.Settings; using BTCPayServer.Services; using BTCPayServer.Services.Stores; using BTCPayServer.Services.Wallets; @@ -19,7 +17,7 @@ using NBitcoin; using NBXplorer; using NBXplorer.DerivationStrategy; using PayoutData = BTCPayServer.Data.PayoutData; -using PayoutProcessorData = BTCPayServer.Data.Data.PayoutProcessorData; +using PayoutProcessorData = BTCPayServer.Data.PayoutProcessorData; namespace BTCPayServer.PayoutProcessors.OnChain { diff --git a/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutSenderFactory.cs b/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutSenderFactory.cs index 26b75a3f8..66a90adf0 100644 --- a/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutSenderFactory.cs +++ b/BTCPayServer/PayoutProcessors/OnChain/OnChainAutomatedPayoutSenderFactory.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using BTCPayServer.Data.Data; +using BTCPayServer.Data; using BTCPayServer.HostedServices; using BTCPayServer.Payments; using Microsoft.AspNetCore.Http; diff --git a/BTCPayServer/PayoutProcessors/OnChain/UIOnChainAutomatedPayoutProcessorsController.cs b/BTCPayServer/PayoutProcessors/OnChain/UIOnChainAutomatedPayoutProcessorsController.cs index b30ec85e8..a6f977a68 100644 --- a/BTCPayServer/PayoutProcessors/OnChain/UIOnChainAutomatedPayoutProcessorsController.cs +++ b/BTCPayServer/PayoutProcessors/OnChain/UIOnChainAutomatedPayoutProcessorsController.cs @@ -6,9 +6,8 @@ using BTCPayServer.Abstractions.Constants; using BTCPayServer.Abstractions.Extensions; using BTCPayServer.Abstractions.Models; using BTCPayServer.Client; -using BTCPayServer.Data.Data; +using BTCPayServer.Data; using BTCPayServer.Payments; -using BTCPayServer.PayoutProcessors.Settings; using BTCPayServer.Services.Invoices; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -103,7 +102,7 @@ public class UIOnChainAutomatedPayoutProcessorsController : Controller })) .FirstOrDefault(); activeProcessor ??= new PayoutProcessorData(); - activeProcessor.Blob = InvoiceRepository.ToBytes(automatedTransferBlob.ToBlob()); + activeProcessor.HasTypedBlob().SetBlob(automatedTransferBlob.ToBlob()); activeProcessor.StoreId = storeId; activeProcessor.PaymentMethod = new PaymentMethodId(cryptoCode, BitcoinPaymentType.Instance).ToString(); activeProcessor.Processor = _onChainAutomatedPayoutSenderFactory.Processor; diff --git a/BTCPayServer/PayoutProcessors/PayoutProcessorService.cs b/BTCPayServer/PayoutProcessors/PayoutProcessorService.cs index ee0fdbf01..036e633b9 100644 --- a/BTCPayServer/PayoutProcessors/PayoutProcessorService.cs +++ b/BTCPayServer/PayoutProcessors/PayoutProcessorService.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using BTCPayServer.Data; -using BTCPayServer.Data.Data; using BTCPayServer.HostedServices; using BTCPayServer.Logging; using Microsoft.EntityFrameworkCore; diff --git a/BTCPayServer/PayoutProcessors/PayoutProcessorsExtensions.cs b/BTCPayServer/PayoutProcessors/PayoutProcessorsExtensions.cs index 5b2bfa115..8ca48bf7d 100644 --- a/BTCPayServer/PayoutProcessors/PayoutProcessorsExtensions.cs +++ b/BTCPayServer/PayoutProcessors/PayoutProcessorsExtensions.cs @@ -1,4 +1,4 @@ -using BTCPayServer.Data.Data; +using BTCPayServer.Data; using BTCPayServer.Payments; using BTCPayServer.PayoutProcessors.Lightning; using BTCPayServer.PayoutProcessors.OnChain; diff --git a/BTCPayServer/PayoutProcessors/Settings/AutomatedPayoutBlob.cs b/BTCPayServer/PayoutProcessors/Settings/AutomatedPayoutBlob.cs deleted file mode 100644 index 4043fe637..000000000 --- a/BTCPayServer/PayoutProcessors/Settings/AutomatedPayoutBlob.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; - -namespace BTCPayServer.PayoutProcessors.Settings; - -public class AutomatedPayoutBlob -{ - public TimeSpan Interval { get; set; } = TimeSpan.FromHours(1); -} diff --git a/BTCPayServer/PayoutProcessors/UIPayoutProcessorsController.cs b/BTCPayServer/PayoutProcessors/UIPayoutProcessorsController.cs index 05607410d..1208e5707 100644 --- a/BTCPayServer/PayoutProcessors/UIPayoutProcessorsController.cs +++ b/BTCPayServer/PayoutProcessors/UIPayoutProcessorsController.cs @@ -6,7 +6,6 @@ using BTCPayServer.Abstractions.Extensions; using BTCPayServer.Abstractions.Models; using BTCPayServer.Client; using BTCPayServer.Data; -using BTCPayServer.Data.Data; using BTCPayServer.Payments; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/BTCPayServer/Security/GreenField/APIKeysAuthenticationHandler.cs b/BTCPayServer/Security/GreenField/APIKeysAuthenticationHandler.cs index f26bb1101..c112c0d1a 100644 --- a/BTCPayServer/Security/GreenField/APIKeysAuthenticationHandler.cs +++ b/BTCPayServer/Security/GreenField/APIKeysAuthenticationHandler.cs @@ -68,7 +68,7 @@ namespace BTCPayServer.Security.Greenfield claims.Add(new Claim(_identityOptions.CurrentValue.ClaimsIdentity.UserIdClaimType, key.UserId)); claims.AddRange((await _userManager.GetRolesAsync(key.User)).Select(s => new Claim(_identityOptions.CurrentValue.ClaimsIdentity.RoleClaimType, s))); - claims.AddRange(Permission.ToPermissions(key.GetBlob().Permissions).Select(permission => + claims.AddRange(Permission.ToPermissions(key.GetBlob()?.Permissions ?? Array.Empty()).Select(permission => new Claim(GreenfieldConstants.ClaimTypes.Permission, permission.ToString()))); return AuthenticateResult.Success(new AuthenticationTicket( new ClaimsPrincipal(new ClaimsIdentity(claims, GreenfieldConstants.AuthenticationType)), diff --git a/BTCPayServer/Services/Invoices/InvoiceEntity.cs b/BTCPayServer/Services/Invoices/InvoiceEntity.cs index 116fed723..4cd1f98b6 100644 --- a/BTCPayServer/Services/Invoices/InvoiceEntity.cs +++ b/BTCPayServer/Services/Invoices/InvoiceEntity.cs @@ -1274,7 +1274,6 @@ namespace BTCPayServer.Services.Invoices if (string.IsNullOrEmpty(CryptoPaymentDataType)) { paymentType = BitcoinPaymentType.Instance; - ; } else if (!PaymentTypes.TryParse(CryptoPaymentDataType, out paymentType)) { diff --git a/BTCPayServer/Services/Invoices/InvoiceRepository.cs b/BTCPayServer/Services/Invoices/InvoiceRepository.cs index 4f64603d1..b47f174e7 100644 --- a/BTCPayServer/Services/Invoices/InvoiceRepository.cs +++ b/BTCPayServer/Services/Invoices/InvoiceRepository.cs @@ -22,7 +22,7 @@ namespace BTCPayServer.Services.Invoices { public class InvoiceRepository { - static JsonSerializerSettings DefaultSerializerSettings; + internal static JsonSerializerSettings DefaultSerializerSettings; static InvoiceRepository() { DefaultSerializerSettings = new JsonSerializerSettings(); @@ -147,7 +147,7 @@ namespace BTCPayServer.Services.Invoices var expiry = DateTimeOffset.Now + seconds; invoice.ExpirationTime = expiry; invoice.MonitoringExpiration = expiry.AddHours(1); - invoiceData.Blob = ToBytes(invoice, _btcPayNetworkProvider.DefaultNetwork); + invoiceData.SetBlob(invoice); await ctx.SaveChangesAsync(); @@ -168,8 +168,7 @@ namespace BTCPayServer.Services.Invoices var invoice = invoiceData.GetBlob(_btcPayNetworkProvider); invoice.MonitoringExpiration = invoice.MonitoringExpiration.AddHours(1); - invoiceData.Blob = ToBytes(invoice, null); - + invoiceData.SetBlob(invoice); await ctx.SaveChangesAsync(); } @@ -190,7 +189,6 @@ namespace BTCPayServer.Services.Invoices StoreDataId = storeId, Id = invoice.Id, Created = invoice.InvoiceTime, - Blob = ToBytes(invoice, null), OrderId = invoice.Metadata.OrderId, #pragma warning disable CS0618 // Type or member is obsolete Status = invoice.StatusString, @@ -199,6 +197,7 @@ namespace BTCPayServer.Services.Invoices CustomerEmail = invoice.RefundMail, Archived = false }; + invoiceData.SetBlob(invoice); await context.Invoices.AddAsync(invoiceData); @@ -247,7 +246,7 @@ namespace BTCPayServer.Services.Invoices private InvoiceEntity Clone(InvoiceEntity invoice) { var temp = new InvoiceData(); - temp.Blob = ToBytes(invoice); + temp.SetBlob(invoice); return temp.GetBlob(_btcPayNetworkProvider); } @@ -307,7 +306,7 @@ namespace BTCPayServer.Services.Invoices } #pragma warning restore CS0618 invoiceEntity.SetPaymentMethod(paymentMethod); - invoice.Blob = ToBytes(invoiceEntity, network); + invoice.SetBlob(invoiceEntity); await context.AddressInvoices.AddAsync(new AddressInvoiceData() { @@ -341,7 +340,7 @@ namespace BTCPayServer.Services.Invoices .Set(GetDestination(paymentMethod), paymentMethod.GetId())); } invoiceEntity.SetPaymentMethod(paymentMethod); - invoice.Blob = ToBytes(invoiceEntity, network); + invoice.SetBlob(invoiceEntity); AddToTextSearch(context, invoice, paymentMethod.GetPaymentMethodDetails().GetPaymentDestination()); await context.SaveChangesAsync(); } @@ -416,7 +415,7 @@ namespace BTCPayServer.Services.Invoices var blob = invoiceData.GetBlob(_btcPayNetworkProvider); blob.Price = invoice.Price; AddToTextSearch(context, invoiceData, new[] { invoice.Price.ToString(CultureInfo.InvariantCulture) }); - invoiceData.Blob = ToBytes(blob, null); + invoiceData.SetBlob(blob); await context.SaveChangesAsync().ConfigureAwait(false); } @@ -478,7 +477,7 @@ namespace BTCPayServer.Services.Invoices } blob.Metadata = newMetadata; - invoiceData.Blob = ToBytes(blob); + invoiceData.SetBlob(blob); await context.SaveChangesAsync().ConfigureAwait(false); return ToEntity(invoiceData); } @@ -770,22 +769,12 @@ namespace BTCPayServer.Services.Invoices return status; } - public static byte[] ToBytes(T obj, BTCPayNetworkBase network = null) - { - return ZipUtils.Zip(ToJsonString(obj, network)); - } - public static T FromBytes(byte[] blob, BTCPayNetworkBase network = null) { return network == null ? JsonConvert.DeserializeObject(ZipUtils.Unzip(blob), DefaultSerializerSettings) : network.ToObject(ZipUtils.Unzip(blob)); } - - public static string ToJsonString(T data, BTCPayNetworkBase network) - { - return network == null ? JsonConvert.SerializeObject(data, DefaultSerializerSettings) : network.ToString(data); - } } public class InvoiceQuery diff --git a/BTCPayServer/Services/Invoices/PaymentService.cs b/BTCPayServer/Services/Invoices/PaymentService.cs index 78ded5c50..75493a167 100644 --- a/BTCPayServer/Services/Invoices/PaymentService.cs +++ b/BTCPayServer/Services/Invoices/PaymentService.cs @@ -65,16 +65,15 @@ namespace BTCPayServer.Services.Invoices bitcoinPaymentMethod.NextNetworkFee = bitcoinPaymentMethod.NetworkFeeRate.GetFee(100); // assume price for 100 bytes paymentMethod.SetPaymentMethodDetails(bitcoinPaymentMethod); invoiceEntity.SetPaymentMethod(paymentMethod); - invoice.Blob = InvoiceRepository.ToBytes(invoiceEntity, network); + invoice.SetBlob(invoiceEntity); } PaymentData data = new PaymentData { Id = paymentData.GetPaymentId(), - Blob = InvoiceRepository.ToBytes(entity, entity.Network), InvoiceDataId = invoiceId, Accounted = accounted }; - + data.SetBlob(entity); await context.Payments.AddAsync(data); InvoiceRepository.AddToTextSearch(context, invoice, paymentData.GetSearchTerms()); @@ -123,7 +122,7 @@ namespace BTCPayServer.Services.Invoices } dbPayment.Accounted = payment.Value.entity.Accounted; - dbPayment.Blob = InvoiceRepository.ToBytes(payment.Value.entity, payment.Value.entity.Network); + dbPayment.SetBlob(payment.Value.entity); } await context.SaveChangesAsync().ConfigureAwait(false); eventsToSend.ForEach(_eventAggregator.Publish); diff --git a/BTCPayServer/Services/Notifications/NotificationManager.cs b/BTCPayServer/Services/Notifications/NotificationManager.cs index 7f19c159b..17f0c5d66 100644 --- a/BTCPayServer/Services/Notifications/NotificationManager.cs +++ b/BTCPayServer/Services/Notifications/NotificationManager.cs @@ -154,15 +154,15 @@ namespace BTCPayServer.Services.Notifications var handler = GetHandler(data.NotificationType); if (handler is null) return null; - var notification = JsonConvert.DeserializeObject(ZipUtils.Unzip(data.Blob), handler.NotificationBlobType); - var obj = new NotificationViewModel - { - Id = data.Id, - Type = data.NotificationType, - Created = data.Created, - Seen = data.Seen - }; - handler.FillViewModel(notification, obj); + var notification = data.HasTypedBlob(handler.NotificationBlobType).GetBlob(); + var obj = new NotificationViewModel + { + Id = data.Id, + Type = data.NotificationType, + Created = data.Created, + Seen = data.Seen + }; + handler.FillViewModel(notification, obj); return obj; } diff --git a/BTCPayServer/Services/Notifications/NotificationSender.cs b/BTCPayServer/Services/Notifications/NotificationSender.cs index 98f492f2b..cb161d234 100644 --- a/BTCPayServer/Services/Notifications/NotificationSender.cs +++ b/BTCPayServer/Services/Notifications/NotificationSender.cs @@ -40,16 +40,15 @@ namespace BTCPayServer.Services.Notifications { foreach (var uid in users) { - var obj = JsonConvert.SerializeObject(notification); var data = new NotificationData { Id = Guid.NewGuid().ToString(), Created = DateTimeOffset.UtcNow, ApplicationUserId = uid, NotificationType = notification.NotificationType, - Blob = ZipUtils.Zip(obj), Seen = false }; + data.HasTypedBlob().SetBlob(notification); await db.Notifications.AddAsync(data); } await db.SaveChangesAsync(); diff --git a/BTCPayServer/Views/UIForms/FormsList.cshtml b/BTCPayServer/Views/UIForms/FormsList.cshtml index 57d0fa09c..b289a5d4f 100644 --- a/BTCPayServer/Views/UIForms/FormsList.cshtml +++ b/BTCPayServer/Views/UIForms/FormsList.cshtml @@ -1,6 +1,6 @@ @using Microsoft.AspNetCore.Mvc.TagHelpers @using BTCPayServer.Abstractions.Models -@model List +@model List @{ Layout = "../Shared/_NavLayout.cshtml"; ViewData["NavPartialName"] = "../UIStores/_Nav"; diff --git a/BTCPayServer/Views/UIInvoice/InvoiceStatusChangePartial.cshtml b/BTCPayServer/Views/UIInvoice/InvoiceStatusChangePartial.cshtml index 69dfd5c07..6edb50ced 100644 --- a/BTCPayServer/Views/UIInvoice/InvoiceStatusChangePartial.cshtml +++ b/BTCPayServer/Views/UIInvoice/InvoiceStatusChangePartial.cshtml @@ -1,7 +1,7 @@ -@inject UserManager _userManager +@inject UserManager _userManager @* This is a temporary infobox to inform users about the state changes in 1.4.0. It should be removed eventually. *@ -@if ((await _userManager.GetUserAsync(User)).GetBlob().ShowInvoiceStatusChangeHint) +@if ((await _userManager.GetUserAsync(User)).GetBlob()?.ShowInvoiceStatusChangeHint is true) {