mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-03-09 16:04:43 +01:00
Remove MySQL and Sqlite deps (#5910)
This commit is contained in:
parent
9699b3837b
commit
f1a04a3bd0
86 changed files with 818 additions and 1729 deletions
|
@ -33,9 +33,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="HtmlSanitizer" Version="8.0.838" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.1" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.0-beta.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BTCPayServer.Client\BTCPayServer.Client.csproj" />
|
||||
|
|
|
@ -13,12 +13,12 @@ namespace BTCPayServer.Abstractions.Contracts
|
|||
public abstract class BaseDbContextFactory<T> where T : DbContext
|
||||
{
|
||||
private readonly IOptions<DatabaseOptions> _options;
|
||||
private readonly string _schemaPrefix;
|
||||
private readonly string _migrationTableName;
|
||||
|
||||
public BaseDbContextFactory(IOptions<DatabaseOptions> options, string schemaPrefix)
|
||||
public BaseDbContextFactory(IOptions<DatabaseOptions> options, string migrationTableName)
|
||||
{
|
||||
_options = options;
|
||||
_schemaPrefix = schemaPrefix;
|
||||
_migrationTableName = migrationTableName;
|
||||
}
|
||||
|
||||
public abstract T CreateContext();
|
||||
|
@ -68,43 +68,16 @@ namespace BTCPayServer.Abstractions.Contracts
|
|||
|
||||
public void ConfigureBuilder(DbContextOptionsBuilder builder)
|
||||
{
|
||||
switch (_options.Value.DatabaseType)
|
||||
builder
|
||||
.UseNpgsql(_options.Value.ConnectionString, o =>
|
||||
{
|
||||
case DatabaseType.Sqlite:
|
||||
builder.UseSqlite(_options.Value.ConnectionString, o =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_schemaPrefix))
|
||||
{
|
||||
o.MigrationsHistoryTable(_schemaPrefix);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case DatabaseType.Postgres:
|
||||
builder
|
||||
.UseNpgsql(_options.Value.ConnectionString, o =>
|
||||
{
|
||||
o.EnableRetryOnFailure(10);
|
||||
o.SetPostgresVersion(12, 0);
|
||||
var mainSearchPath = GetSearchPath(_options.Value.ConnectionString);
|
||||
var schemaPrefix = string.IsNullOrEmpty(_schemaPrefix) ? "__EFMigrationsHistory" : _schemaPrefix;
|
||||
o.MigrationsHistoryTable(schemaPrefix, mainSearchPath);
|
||||
})
|
||||
.ReplaceService<IMigrationsSqlGenerator, CustomNpgsqlMigrationsSqlGenerator>();
|
||||
break;
|
||||
case DatabaseType.MySQL:
|
||||
builder.UseMySql(_options.Value.ConnectionString, ServerVersion.AutoDetect(_options.Value.ConnectionString), o =>
|
||||
{
|
||||
o.EnableRetryOnFailure(10);
|
||||
|
||||
if (!string.IsNullOrEmpty(_schemaPrefix))
|
||||
{
|
||||
o.MigrationsHistoryTable(_schemaPrefix);
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
o.EnableRetryOnFailure(10);
|
||||
o.SetPostgresVersion(12, 0);
|
||||
var mainSearchPath = GetSearchPath(_options.Value.ConnectionString);
|
||||
var schemaPrefix = string.IsNullOrEmpty(_migrationTableName) ? "__EFMigrationsHistory" : _migrationTableName;
|
||||
o.MigrationsHistoryTable(schemaPrefix, mainSearchPath);
|
||||
})
|
||||
.ReplaceService<IMigrationsSqlGenerator, CustomNpgsqlMigrationsSqlGenerator>();
|
||||
}
|
||||
|
||||
private string GetSearchPath(string connectionString)
|
||||
|
|
|
@ -2,7 +2,6 @@ namespace BTCPayServer.Abstractions.Models
|
|||
{
|
||||
public class DatabaseOptions
|
||||
{
|
||||
public DatabaseType DatabaseType { get; set; }
|
||||
public string ConnectionString { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
namespace BTCPayServer.Abstractions.Models
|
||||
{
|
||||
public enum DatabaseType
|
||||
{
|
||||
Sqlite,
|
||||
Postgres,
|
||||
MySQL,
|
||||
}
|
||||
}
|
|
@ -12,30 +12,18 @@ namespace BTCPayServer.Data
|
|||
{
|
||||
public ApplicationDbContext CreateDbContext(string[] args)
|
||||
{
|
||||
|
||||
var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
|
||||
|
||||
builder.UseSqlite("Data Source=temp.db");
|
||||
|
||||
return new ApplicationDbContext(builder.Options, true);
|
||||
// Same as launchsettings.json, it's connecting to the docker's postgres.
|
||||
builder.UseNpgsql("User ID=postgres;Include Error Detail=true;Host=127.0.0.1;Port=39372;Database=btcpayserver");
|
||||
return new ApplicationDbContext(builder.Options);
|
||||
}
|
||||
}
|
||||
|
||||
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
|
||||
{
|
||||
private readonly bool _designTime;
|
||||
|
||||
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, bool designTime = false)
|
||||
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
|
||||
: base(options)
|
||||
{
|
||||
_designTime = designTime;
|
||||
}
|
||||
#nullable enable
|
||||
public async Task<string?> GetMigrationState()
|
||||
{
|
||||
return (await Settings.FromSqlRaw("SELECT \"Id\", \"Value\" FROM \"Settings\" WHERE \"Id\"='MigrationData'").AsNoTracking().FirstOrDefaultAsync())?.Value;
|
||||
}
|
||||
#nullable restore
|
||||
public DbSet<AddressInvoiceData> AddressInvoices { get; set; }
|
||||
public DbSet<APIKeyData> ApiKeys { get; set; }
|
||||
public DbSet<AppData> Apps { get; set; }
|
||||
|
@ -76,13 +64,6 @@ namespace BTCPayServer.Data
|
|||
public DbSet<PayoutProcessorData> PayoutProcessors { get; set; }
|
||||
public DbSet<FormData> Forms { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
var isConfigured = optionsBuilder.Options.Extensions.OfType<RelationalOptionsExtension>().Any();
|
||||
if (!isConfigured)
|
||||
optionsBuilder.UseSqlite("Data Source=temp.db");
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
base.OnModelCreating(builder);
|
||||
|
@ -129,28 +110,6 @@ namespace BTCPayServer.Data
|
|||
WebhookData.OnModelCreating(builder, Database);
|
||||
FormData.OnModelCreating(builder, Database);
|
||||
StoreRole.OnModelCreating(builder, Database);
|
||||
|
||||
|
||||
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
|
||||
// To work around this, when the Sqlite database provider is used, all model properties of type DateTimeOffset
|
||||
// use the DateTimeOffsetToBinaryConverter
|
||||
// Based on: https://github.com/aspnet/EntityFrameworkCore/issues/10784#issuecomment-415769754
|
||||
// This only supports millisecond precision, but should be sufficient for most use cases.
|
||||
foreach (var entityType in builder.Model.GetEntityTypes())
|
||||
{
|
||||
var properties = entityType.ClrType.GetProperties().Where(p => p.PropertyType == typeof(DateTimeOffset));
|
||||
foreach (var property in properties)
|
||||
{
|
||||
builder
|
||||
.Entity(entityType.Name)
|
||||
.Property(property.Name)
|
||||
.HasConversion(new Microsoft.EntityFrameworkCore.Storage.ValueConversion.DateTimeOffsetToBinaryConverter());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,12 +41,9 @@ namespace BTCPayServer.Data
|
|||
builder.Entity<APIKeyData>()
|
||||
.HasIndex(o => o.StoreId);
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<APIKeyData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
builder.Entity<APIKeyData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,12 +25,9 @@ namespace BTCPayServer.Data
|
|||
builder.Entity<AppData>()
|
||||
.HasOne(a => a.StoreData);
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<AppData>()
|
||||
.Property(o => o.Settings)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
builder.Entity<AppData>()
|
||||
.Property(o => o.Settings)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
|
||||
// utility methods
|
||||
|
|
|
@ -35,12 +35,10 @@ namespace BTCPayServer.Data
|
|||
builder.Entity<ApplicationUser>()
|
||||
.HasMany<IdentityUserRole<string>>(user => user.UserRoles)
|
||||
.WithOne().HasForeignKey(role => role.UserId);
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<ApplicationUser>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
|
||||
builder.Entity<ApplicationUser>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,12 +30,10 @@ namespace BTCPayServer.Data
|
|||
.HasOne(o => o.ApplicationUser)
|
||||
.WithMany(i => i.Fido2Credentials)
|
||||
.HasForeignKey(i => i.ApplicationUserId).OnDelete(DeleteBehavior.Cascade);
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<Fido2Credential>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
|
||||
builder.Entity<Fido2Credential>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
|
||||
public ApplicationUser ApplicationUser { get; set; }
|
||||
|
|
|
@ -21,11 +21,8 @@ public class FormData
|
|||
.WithMany(o => o.Forms).OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<FormData>().HasIndex(o => o.StoreId);
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<FormData>()
|
||||
.Property(o => o.Config)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
builder.Entity<FormData>()
|
||||
.Property(o => o.Config)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,15 +44,12 @@ namespace BTCPayServer.Data
|
|||
builder.Entity<InvoiceData>().HasIndex(o => o.StoreDataId);
|
||||
builder.Entity<InvoiceData>().HasIndex(o => o.OrderId);
|
||||
builder.Entity<InvoiceData>().HasIndex(o => o.Created);
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<InvoiceData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
builder.Entity<InvoiceData>()
|
||||
.Property(o => o.Amount)
|
||||
.HasColumnType("NUMERIC");
|
||||
}
|
||||
builder.Entity<InvoiceData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
builder.Entity<InvoiceData>()
|
||||
.Property(o => o.Amount)
|
||||
.HasColumnType("NUMERIC");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,12 +27,9 @@ public class LightningAddressData : IHasBlob<LightningAddressDataBlob>
|
|||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<LightningAddressData>().HasKey(o => o.Username);
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<LightningAddressData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
builder.Entity<LightningAddressData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,12 +30,9 @@ namespace BTCPayServer.Data
|
|||
.HasOne(o => o.ApplicationUser)
|
||||
.WithMany(n => n.Notifications)
|
||||
.HasForeignKey(k => k.ApplicationUserId).OnDelete(DeleteBehavior.Cascade);
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<NotificationData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
builder.Entity<NotificationData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,15 +41,12 @@ namespace BTCPayServer.Data
|
|||
builder.Entity<PaymentData>()
|
||||
.Property(o => o.Status)
|
||||
.HasConversion<string>();
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<PaymentData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
builder.Entity<PaymentData>()
|
||||
.Property(o => o.Amount)
|
||||
.HasColumnType("NUMERIC");
|
||||
}
|
||||
builder.Entity<PaymentData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
builder.Entity<PaymentData>()
|
||||
.Property(o => o.Amount)
|
||||
.HasColumnType("NUMERIC");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,12 +32,9 @@ namespace BTCPayServer.Data
|
|||
builder.Entity<PaymentRequestData>()
|
||||
.HasIndex(o => o.Status);
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<PaymentRequestData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
builder.Entity<PaymentRequestData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,32 +47,12 @@ namespace BTCPayServer.Data
|
|||
builder.Entity<PayoutData>()
|
||||
.HasIndex(x => new { DestinationId = x.Destination, x.State });
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<PayoutData>()
|
||||
.Property(o => o.Blob)
|
||||
.HasColumnType("JSONB");
|
||||
builder.Entity<PayoutData>()
|
||||
.Property(o => o.Proof)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
else if (databaseFacade.IsMySql())
|
||||
{
|
||||
builder.Entity<PayoutData>()
|
||||
.Property(o => o.Blob)
|
||||
.HasConversion(new ValueConverter<string, byte[]>
|
||||
(
|
||||
convertToProviderExpression: (str) => Encoding.UTF8.GetBytes(str),
|
||||
convertFromProviderExpression: (bytes) => Encoding.UTF8.GetString(bytes)
|
||||
));
|
||||
builder.Entity<PayoutData>()
|
||||
.Property(o => o.Proof)
|
||||
.HasConversion(new ValueConverter<string, byte[]>
|
||||
(
|
||||
convertToProviderExpression: (str) => Encoding.UTF8.GetBytes(str),
|
||||
convertFromProviderExpression: (bytes) => Encoding.UTF8.GetString(bytes)
|
||||
));
|
||||
}
|
||||
builder.Entity<PayoutData>()
|
||||
.Property(o => o.Blob)
|
||||
.HasColumnType("JSONB");
|
||||
builder.Entity<PayoutData>()
|
||||
.Property(o => o.Proof)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
|
||||
// utility methods
|
||||
|
|
|
@ -29,12 +29,9 @@ public class PayoutProcessorData : IHasBlobUntyped
|
|||
.HasOne(o => o.Store)
|
||||
.WithMany(data => data.PayoutProcessors).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<PayoutProcessorData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
builder.Entity<PayoutProcessorData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
|
|
@ -38,22 +38,9 @@ namespace BTCPayServer.Data
|
|||
.HasOne(o => o.StoreData)
|
||||
.WithMany(o => o.PullPayments).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<PullPaymentData>()
|
||||
.Property(o => o.Blob)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
else if (databaseFacade.IsMySql())
|
||||
{
|
||||
builder.Entity<PullPaymentData>()
|
||||
.Property(o => o.Blob)
|
||||
.HasConversion(new ValueConverter<string, byte[]>
|
||||
(
|
||||
convertToProviderExpression: (str) => Encoding.UTF8.GetBytes(str),
|
||||
convertFromProviderExpression: (bytes) => Encoding.UTF8.GetString(bytes)
|
||||
));
|
||||
}
|
||||
builder.Entity<PullPaymentData>()
|
||||
.Property(o => o.Blob)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
|
||||
public (DateTimeOffset Start, DateTimeOffset? End)? GetPeriod(DateTimeOffset now)
|
||||
|
|
|
@ -11,12 +11,9 @@ namespace BTCPayServer.Data
|
|||
|
||||
public static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<SettingData>()
|
||||
.Property(o => o.Value)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
builder.Entity<SettingData>()
|
||||
.Property(o => o.Value)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,26 +52,13 @@ namespace BTCPayServer.Data
|
|||
|
||||
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<StoreData>()
|
||||
.Property(o => o.StoreBlob)
|
||||
.HasColumnType("JSONB");
|
||||
builder.Entity<StoreData>()
|
||||
.Property(o => o.StoreBlob)
|
||||
.HasColumnType("JSONB");
|
||||
|
||||
builder.Entity<StoreData>()
|
||||
.Property(o => o.DerivationStrategies)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
else if (databaseFacade.IsMySql())
|
||||
{
|
||||
builder.Entity<StoreData>()
|
||||
.Property(o => o.StoreBlob)
|
||||
.HasConversion(new ValueConverter<string, byte[]>
|
||||
(
|
||||
convertToProviderExpression: (str) => Encoding.UTF8.GetBytes(str),
|
||||
convertFromProviderExpression: (bytes) => Encoding.UTF8.GetString(bytes)
|
||||
));
|
||||
}
|
||||
builder.Entity<StoreData>()
|
||||
.Property(o => o.DerivationStrategies)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,20 +31,5 @@ public class StoreRole
|
|||
|
||||
entity.HasIndex(entity => new {entity.StoreDataId, entity.Role}).IsUnique();
|
||||
});
|
||||
|
||||
|
||||
|
||||
if (!databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<StoreRole>()
|
||||
.Property(o => o.Permissions)
|
||||
.HasConversion(
|
||||
v => JsonConvert.SerializeObject(v),
|
||||
v => JsonConvert.DeserializeObject<List<string>>(v)?? new List<string>(),
|
||||
new ValueComparer<List<string>>(
|
||||
(c1, c2) => c1 ==c2 || c1 != null && c2 != null && c1.SequenceEqual(c2),
|
||||
c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
|
||||
c => c.ToList()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,11 +18,9 @@ public class StoreSettingData
|
|||
builder.Entity<StoreSettingData>()
|
||||
.HasOne(o => o.Store)
|
||||
.WithMany(o => o.Settings).OnDelete(DeleteBehavior.Cascade);
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<StoreSettingData>()
|
||||
.Property(o => o.Value)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
|
||||
builder.Entity<StoreSettingData>()
|
||||
.Property(o => o.Value)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,13 +83,9 @@ namespace BTCPayServer.Data
|
|||
o.Id
|
||||
});
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<WalletObjectData>()
|
||||
.Property(o => o.Data)
|
||||
.HasColumnType("JSONB");
|
||||
|
||||
}
|
||||
builder.Entity<WalletObjectData>()
|
||||
.Property(o => o.Data)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
|
||||
public bool Equals(WalletObjectData x, WalletObjectData y)
|
||||
|
|
|
@ -50,12 +50,9 @@ namespace BTCPayServer.Data
|
|||
.HasForeignKey(o => new { o.WalletId, o.BType, o.BId })
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<WalletObjectLinkData>()
|
||||
.Property(o => o.Data)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
builder.Entity<WalletObjectLinkData>()
|
||||
.Property(o => o.Data)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,12 +18,9 @@ namespace BTCPayServer.Data
|
|||
|
||||
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<WebhookData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
builder.Entity<WebhookData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,12 +27,9 @@ namespace BTCPayServer.Data
|
|||
.WithMany(a => a.Deliveries).OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<WebhookDeliveryData>().HasIndex(o => o.WebhookId);
|
||||
builder.Entity<WebhookDeliveryData>().HasIndex(o => o.Timestamp);
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<WebhookDeliveryData>()
|
||||
.Property(o => o.Blob)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
builder.Entity<WebhookDeliveryData>()
|
||||
.Property(o => o.Blob)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,12 +11,11 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetRoles",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
ConcurrencyStamp = table.Column<string>(nullable: true),
|
||||
Name = table.Column<string>(maxLength: 256, nullable: true),
|
||||
NormalizedName = table.Column<string>(maxLength: 256, nullable: true)
|
||||
|
@ -30,7 +29,7 @@ namespace BTCPayServer.Migrations
|
|||
name: "AspNetUsers",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
AccessFailedCount = table.Column<int>(nullable: false),
|
||||
ConcurrencyStamp = table.Column<string>(nullable: true),
|
||||
Email = table.Column<string>(maxLength: 256, nullable: true),
|
||||
|
@ -55,7 +54,7 @@ namespace BTCPayServer.Migrations
|
|||
name: "Stores",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
DerivationStrategy = table.Column<string>(nullable: true),
|
||||
SpeedPolicy = table.Column<int>(nullable: false),
|
||||
StoreCertificate = table.Column<byte[]>(nullable: true),
|
||||
|
@ -75,7 +74,7 @@ namespace BTCPayServer.Migrations
|
|||
.Annotation("Sqlite:Autoincrement", true),
|
||||
ClaimType = table.Column<string>(nullable: true),
|
||||
ClaimValue = table.Column<string>(nullable: true),
|
||||
RoleId = table.Column<string>(nullable: false, maxLength: maxLength)
|
||||
RoleId = table.Column<string>(nullable: false, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
@ -96,7 +95,7 @@ namespace BTCPayServer.Migrations
|
|||
.Annotation("Sqlite:Autoincrement", true),
|
||||
ClaimType = table.Column<string>(nullable: true),
|
||||
ClaimValue = table.Column<string>(nullable: true),
|
||||
UserId = table.Column<string>(nullable: false, maxLength: maxLength)
|
||||
UserId = table.Column<string>(nullable: false, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
@ -116,7 +115,7 @@ namespace BTCPayServer.Migrations
|
|||
LoginProvider = table.Column<string>(nullable: false, maxLength: 255),
|
||||
ProviderKey = table.Column<string>(nullable: false, maxLength: 255),
|
||||
ProviderDisplayName = table.Column<string>(nullable: true),
|
||||
UserId = table.Column<string>(nullable: false, maxLength: maxLength)
|
||||
UserId = table.Column<string>(nullable: false, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
@ -133,8 +132,8 @@ namespace BTCPayServer.Migrations
|
|||
name: "AspNetUserRoles",
|
||||
columns: table => new
|
||||
{
|
||||
UserId = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
RoleId = table.Column<string>(nullable: false, maxLength: maxLength)
|
||||
UserId = table.Column<string>(nullable: false, maxLength: null),
|
||||
RoleId = table.Column<string>(nullable: false, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
@ -157,7 +156,7 @@ namespace BTCPayServer.Migrations
|
|||
name: "AspNetUserTokens",
|
||||
columns: table => new
|
||||
{
|
||||
UserId = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
UserId = table.Column<string>(nullable: false, maxLength: null),
|
||||
LoginProvider = table.Column<string>(nullable: false, maxLength: 64),
|
||||
Name = table.Column<string>(nullable: false, maxLength: 64),
|
||||
Value = table.Column<string>(nullable: true)
|
||||
|
@ -177,7 +176,7 @@ namespace BTCPayServer.Migrations
|
|||
name: "Invoices",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Blob = table.Column<byte[]>(nullable: true),
|
||||
Created = table.Column<DateTimeOffset>(nullable: false),
|
||||
CustomerEmail = table.Column<string>(nullable: true),
|
||||
|
@ -185,7 +184,7 @@ namespace BTCPayServer.Migrations
|
|||
ItemCode = table.Column<string>(nullable: true),
|
||||
OrderId = table.Column<string>(nullable: true),
|
||||
Status = table.Column<string>(nullable: true),
|
||||
StoreDataId = table.Column<string>(nullable: true, maxLength: maxLength)
|
||||
StoreDataId = table.Column<string>(nullable: true, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
@ -202,8 +201,8 @@ namespace BTCPayServer.Migrations
|
|||
name: "UserStore",
|
||||
columns: table => new
|
||||
{
|
||||
ApplicationUserId = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
StoreDataId = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
ApplicationUserId = table.Column<string>(nullable: false, maxLength: null),
|
||||
StoreDataId = table.Column<string>(nullable: false, maxLength: null),
|
||||
Role = table.Column<string>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
|
@ -227,9 +226,9 @@ namespace BTCPayServer.Migrations
|
|||
name: "Payments",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Blob = table.Column<byte[]>(nullable: true),
|
||||
InvoiceDataId = table.Column<string>(nullable: true, maxLength: maxLength)
|
||||
InvoiceDataId = table.Column<string>(nullable: true, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
@ -246,9 +245,9 @@ namespace BTCPayServer.Migrations
|
|||
name: "RefundAddresses",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Blob = table.Column<byte[]>(nullable: true),
|
||||
InvoiceDataId = table.Column<string>(nullable: true, maxLength: maxLength)
|
||||
InvoiceDataId = table.Column<string>(nullable: true, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
|
|
@ -10,12 +10,11 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Settings",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Value = table.Column<string>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
|
|
|
@ -10,8 +10,7 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "RequiresEmailConfirmation",
|
||||
table: "AspNetUsers",
|
||||
nullable: false,
|
||||
|
|
|
@ -10,13 +10,12 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AddressInvoices",
|
||||
columns: table => new
|
||||
{
|
||||
Address = table.Column<string>(nullable: false, maxLength: this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)512 : null),
|
||||
InvoiceDataId = table.Column<string>(nullable: true, maxLength: maxLength)
|
||||
Address = table.Column<string>(nullable: false, maxLength: null),
|
||||
InvoiceDataId = table.Column<string>(nullable: true, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
|
|
@ -11,18 +11,17 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PairedSINData",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Facade = table.Column<string>(nullable: true),
|
||||
Label = table.Column<string>(nullable: true),
|
||||
Name = table.Column<string>(nullable: true),
|
||||
PairingTime = table.Column<DateTimeOffset>(nullable: false),
|
||||
SIN = table.Column<string>(nullable: true, maxLength: maxLength),
|
||||
StoreDataId = table.Column<string>(nullable: true, maxLength: maxLength)
|
||||
SIN = table.Column<string>(nullable: true, maxLength: null),
|
||||
StoreDataId = table.Column<string>(nullable: true, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
@ -33,14 +32,14 @@ namespace BTCPayServer.Migrations
|
|||
name: "PairingCodes",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
DateCreated = table.Column<DateTime>(nullable: false),
|
||||
Expiration = table.Column<DateTimeOffset>(nullable: false),
|
||||
Facade = table.Column<string>(nullable: true),
|
||||
Label = table.Column<string>(nullable: true),
|
||||
Name = table.Column<string>(nullable: true),
|
||||
SIN = table.Column<string>(nullable: true),
|
||||
StoreDataId = table.Column<string>(nullable: true, maxLength: maxLength),
|
||||
StoreDataId = table.Column<string>(nullable: true, maxLength: null),
|
||||
TokenValue = table.Column<string>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
|
|
|
@ -10,22 +10,18 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
if (this.SupportDropColumn(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Name",
|
||||
table: "PairingCodes");
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Name",
|
||||
table: "PairingCodes");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Name",
|
||||
table: "PairedSINData");
|
||||
}
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Name",
|
||||
table: "PairedSINData");
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PendingInvoices",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength)
|
||||
Id = table.Column<string>(nullable: false, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
|
|
@ -10,8 +10,7 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.AddColumn<byte[]>(
|
||||
migrationBuilder.AddColumn<byte[]>(
|
||||
name: "StoreBlob",
|
||||
table: "Stores",
|
||||
nullable: true);
|
||||
|
|
|
@ -11,7 +11,6 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.AddColumn<DateTimeOffset>(
|
||||
name: "CreatedTime",
|
||||
table: "AddressInvoices",
|
||||
|
@ -21,8 +20,8 @@ namespace BTCPayServer.Migrations
|
|||
name: "HistoricalAddressInvoices",
|
||||
columns: table => new
|
||||
{
|
||||
InvoiceDataId = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Address = table.Column<string>(nullable: false, maxLength: this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)512 : null),
|
||||
InvoiceDataId = table.Column<string>(nullable: false, maxLength: null),
|
||||
Address = table.Column<string>(nullable: false, maxLength: null),
|
||||
Assigned = table.Column<DateTimeOffset>(nullable: false),
|
||||
UnAssigned = table.Column<DateTimeOffset>(nullable: true)
|
||||
},
|
||||
|
|
|
@ -10,8 +10,7 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "Accounted",
|
||||
table: "Payments",
|
||||
nullable: false,
|
||||
|
|
|
@ -10,8 +10,7 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.AddColumn<string>(
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "CryptoCode",
|
||||
table: "HistoricalAddressInvoices",
|
||||
nullable: true);
|
||||
|
|
|
@ -10,8 +10,7 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.AddColumn<string>(
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "DerivationStrategies",
|
||||
table: "Stores",
|
||||
nullable: true);
|
||||
|
|
|
@ -10,8 +10,7 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.AddColumn<string>(
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "DefaultCrypto",
|
||||
table: "Stores",
|
||||
nullable: true);
|
||||
|
|
|
@ -11,13 +11,12 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
migrationBuilder.CreateTable(
|
||||
name: "InvoiceEvents",
|
||||
columns: table => new
|
||||
{
|
||||
InvoiceDataId = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
UniqueId = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
InvoiceDataId = table.Column<string>(nullable: false, maxLength: null),
|
||||
UniqueId = table.Column<string>(nullable: false, maxLength: null),
|
||||
Message = table.Column<string>(nullable: true),
|
||||
Timestamp = table.Column<DateTimeOffset>(nullable: false)
|
||||
},
|
||||
|
|
|
@ -11,17 +11,16 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Apps",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
AppType = table.Column<string>(nullable: true),
|
||||
Created = table.Column<DateTimeOffset>(nullable: false),
|
||||
Name = table.Column<string>(nullable: true),
|
||||
Settings = table.Column<string>(nullable: true),
|
||||
StoreDataId = table.Column<string>(nullable: true, maxLength: maxLength)
|
||||
StoreDataId = table.Column<string>(nullable: true, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
|
|
@ -10,8 +10,7 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ApiKeys",
|
||||
columns: table => new
|
||||
{
|
||||
|
|
|
@ -10,93 +10,89 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
if (this.SupportDropForeignKey(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_AddressInvoices_Invoices_InvoiceDataId",
|
||||
table: "AddressInvoices");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Apps_Stores_StoreDataId",
|
||||
table: "Apps");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Invoices_Stores_StoreDataId",
|
||||
table: "Invoices");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Payments_Invoices_InvoiceDataId",
|
||||
table: "Payments");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_RefundAddresses_Invoices_InvoiceDataId",
|
||||
table: "RefundAddresses");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_AddressInvoices_Invoices_InvoiceDataId",
|
||||
table: "AddressInvoices");
|
||||
table: "AddressInvoices",
|
||||
column: "InvoiceDataId",
|
||||
principalTable: "Invoices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Apps_Stores_StoreDataId",
|
||||
table: "Apps");
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_ApiKeys_Stores_StoreId",
|
||||
table: "ApiKeys",
|
||||
column: "StoreId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Invoices_Stores_StoreDataId",
|
||||
table: "Invoices");
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Apps_Stores_StoreDataId",
|
||||
table: "Apps",
|
||||
column: "StoreDataId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Payments_Invoices_InvoiceDataId",
|
||||
table: "Payments");
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Invoices_Stores_StoreDataId",
|
||||
table: "Invoices",
|
||||
column: "StoreDataId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_RefundAddresses_Invoices_InvoiceDataId",
|
||||
table: "RefundAddresses");
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_PairedSINData_Stores_StoreDataId",
|
||||
table: "PairedSINData",
|
||||
column: "StoreDataId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_AddressInvoices_Invoices_InvoiceDataId",
|
||||
table: "AddressInvoices",
|
||||
column: "InvoiceDataId",
|
||||
principalTable: "Invoices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Payments_Invoices_InvoiceDataId",
|
||||
table: "Payments",
|
||||
column: "InvoiceDataId",
|
||||
principalTable: "Invoices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_ApiKeys_Stores_StoreId",
|
||||
table: "ApiKeys",
|
||||
column: "StoreId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_PendingInvoices_Invoices_Id",
|
||||
table: "PendingInvoices",
|
||||
column: "Id",
|
||||
principalTable: "Invoices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Apps_Stores_StoreDataId",
|
||||
table: "Apps",
|
||||
column: "StoreDataId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Invoices_Stores_StoreDataId",
|
||||
table: "Invoices",
|
||||
column: "StoreDataId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_PairedSINData_Stores_StoreDataId",
|
||||
table: "PairedSINData",
|
||||
column: "StoreDataId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Payments_Invoices_InvoiceDataId",
|
||||
table: "Payments",
|
||||
column: "InvoiceDataId",
|
||||
principalTable: "Invoices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_PendingInvoices_Invoices_Id",
|
||||
table: "PendingInvoices",
|
||||
column: "Id",
|
||||
principalTable: "Invoices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_RefundAddresses_Invoices_InvoiceDataId",
|
||||
table: "RefundAddresses",
|
||||
column: "InvoiceDataId",
|
||||
principalTable: "Invoices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_RefundAddresses_Invoices_InvoiceDataId",
|
||||
table: "RefundAddresses",
|
||||
column: "InvoiceDataId",
|
||||
principalTable: "Invoices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
|
|
|
@ -10,13 +10,12 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PaymentRequests",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
StoreDataId = table.Column<string>(nullable: true, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
StoreDataId = table.Column<string>(nullable: true, maxLength: null),
|
||||
Status = table.Column<int>(nullable: false),
|
||||
Blob = table.Column<byte[]>(nullable: true)
|
||||
},
|
||||
|
|
|
@ -10,8 +10,7 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "TagAllInvoices",
|
||||
table: "Apps",
|
||||
nullable: false,
|
||||
|
|
|
@ -11,8 +11,7 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OpenIddictApplications",
|
||||
columns: table => new
|
||||
{
|
||||
|
@ -21,13 +20,13 @@ namespace BTCPayServer.Migrations
|
|||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
ConsentType = table.Column<string>(nullable: true),
|
||||
DisplayName = table.Column<string>(nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Permissions = table.Column<string>(nullable: true),
|
||||
PostLogoutRedirectUris = table.Column<string>(nullable: true),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
RedirectUris = table.Column<string>(nullable: true),
|
||||
Type = table.Column<string>(maxLength: 25, nullable: false),
|
||||
ApplicationUserId = table.Column<string>(nullable: true, maxLength: maxLength)
|
||||
ApplicationUserId = table.Column<string>(nullable: true, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
@ -47,7 +46,7 @@ namespace BTCPayServer.Migrations
|
|||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
Description = table.Column<string>(nullable: true),
|
||||
DisplayName = table.Column<string>(nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Name = table.Column<string>(maxLength: 200, nullable: false),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
Resources = table.Column<string>(nullable: true)
|
||||
|
@ -61,9 +60,9 @@ namespace BTCPayServer.Migrations
|
|||
name: "OpenIddictAuthorizations",
|
||||
columns: table => new
|
||||
{
|
||||
ApplicationId = table.Column<string>(nullable: true, maxLength: maxLength),
|
||||
ApplicationId = table.Column<string>(nullable: true, maxLength: null),
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
Scopes = table.Column<string>(nullable: true),
|
||||
Status = table.Column<string>(maxLength: 25, nullable: false),
|
||||
|
@ -85,12 +84,12 @@ namespace BTCPayServer.Migrations
|
|||
name: "OpenIddictTokens",
|
||||
columns: table => new
|
||||
{
|
||||
ApplicationId = table.Column<string>(nullable: true, maxLength: maxLength),
|
||||
AuthorizationId = table.Column<string>(nullable: true, maxLength: maxLength),
|
||||
ApplicationId = table.Column<string>(nullable: true, maxLength: null),
|
||||
AuthorizationId = table.Column<string>(nullable: true, maxLength: null),
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
CreationDate = table.Column<DateTimeOffset>(nullable: true),
|
||||
ExpirationDate = table.Column<DateTimeOffset>(nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Payload = table.Column<string>(nullable: true),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
ReferenceId = table.Column<string>(maxLength: 100, nullable: true),
|
||||
|
|
|
@ -11,16 +11,15 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Files",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
FileName = table.Column<string>(nullable: true),
|
||||
StorageFileName = table.Column<string>(nullable: true),
|
||||
Timestamp = table.Column<DateTime>(nullable: false),
|
||||
ApplicationUserId = table.Column<string>(nullable: true, maxLength: maxLength)
|
||||
ApplicationUserId = table.Column<string>(nullable: true, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
|
|
@ -10,25 +10,21 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
if (this.SupportDropColumn(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Facade",
|
||||
table: "PairedSINData");
|
||||
}
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Facade",
|
||||
table: "PairedSINData");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "U2FDevices",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Name = table.Column<string>(nullable: true),
|
||||
KeyHandle = table.Column<byte[]>(nullable: false),
|
||||
PublicKey = table.Column<byte[]>(nullable: false),
|
||||
AttestationCert = table.Column<byte[]>(nullable: false),
|
||||
Counter = table.Column<int>(nullable: false),
|
||||
ApplicationUserId = table.Column<string>(nullable: true, maxLength: maxLength)
|
||||
ApplicationUserId = table.Column<string>(nullable: true, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
@ -52,13 +48,10 @@ namespace BTCPayServer.Migrations
|
|||
migrationBuilder.DropTable(
|
||||
name: "U2FDevices");
|
||||
//if it did not support dropping it, then it is still here and re-adding it would throw
|
||||
if (this.SupportDropColumn(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Facade",
|
||||
table: "PairedSINData",
|
||||
nullable: true);
|
||||
}
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Facade",
|
||||
table: "PairedSINData",
|
||||
nullable: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,7 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.AddColumn<DateTimeOffset>(
|
||||
migrationBuilder.AddColumn<DateTimeOffset>(
|
||||
name: "Created",
|
||||
table: "PaymentRequests",
|
||||
nullable: false,
|
||||
|
|
|
@ -10,12 +10,11 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Wallets",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Blob = table.Column<byte[]>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
|
@ -27,8 +26,8 @@ namespace BTCPayServer.Migrations
|
|||
name: "WalletTransactions",
|
||||
columns: table => new
|
||||
{
|
||||
WalletDataId = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
TransactionId = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
WalletDataId = table.Column<string>(nullable: false, maxLength: null),
|
||||
TransactionId = table.Column<string>(nullable: false, maxLength: null),
|
||||
Labels = table.Column<string>(nullable: true),
|
||||
Blob = table.Column<byte[]>(nullable: true)
|
||||
},
|
||||
|
|
|
@ -11,91 +11,21 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (!migrationBuilder.IsSqlite())
|
||||
{
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Subject",
|
||||
table: "OpenIddictTokens",
|
||||
maxLength: 450,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldMaxLength: 450);
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Subject",
|
||||
table: "OpenIddictTokens",
|
||||
maxLength: 450,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldMaxLength: 450);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Subject",
|
||||
table: "OpenIddictAuthorizations",
|
||||
maxLength: 450,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldMaxLength: 450);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ReplaceOldTable(migrationBuilder, s =>
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: s,
|
||||
columns: table => new
|
||||
{
|
||||
ApplicationId = table.Column<string>(nullable: true, maxLength: null),
|
||||
AuthorizationId = table.Column<string>(nullable: true, maxLength: null),
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
CreationDate = table.Column<DateTimeOffset>(nullable: true),
|
||||
ExpirationDate = table.Column<DateTimeOffset>(nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Payload = table.Column<string>(nullable: true),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
ReferenceId = table.Column<string>(maxLength: 100, nullable: true),
|
||||
Status = table.Column<string>(maxLength: 25, nullable: false),
|
||||
Subject = table.Column<string>(maxLength: 450, nullable: true),
|
||||
Type = table.Column<string>(maxLength: 25, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictTokens", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictTokens_OpenIddictApplications_ApplicationId",
|
||||
column: x => x.ApplicationId,
|
||||
principalTable: "OpenIddictApplications",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictTokens_OpenIddictAuthorizations_AuthorizationId",
|
||||
column: x => x.AuthorizationId,
|
||||
principalTable: "OpenIddictAuthorizations",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
}, "OpenIddictTokens");
|
||||
|
||||
ReplaceOldTable(migrationBuilder, s =>
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: s,
|
||||
columns: table => new
|
||||
{
|
||||
ApplicationId = table.Column<string>(nullable: true, maxLength: null),
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
Scopes = table.Column<string>(nullable: true),
|
||||
Status = table.Column<string>(maxLength: 25, nullable: false),
|
||||
Subject = table.Column<string>(maxLength: 450, nullable: true),
|
||||
Type = table.Column<string>(maxLength: 25, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictAuthorizations", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictAuthorizations_OpenIddictApplications_ApplicationId",
|
||||
column: x => x.ApplicationId,
|
||||
principalTable: "OpenIddictApplications",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
}, "OpenIddictAuthorizations");
|
||||
}
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Subject",
|
||||
table: "OpenIddictAuthorizations",
|
||||
maxLength: 450,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string),
|
||||
oldMaxLength: 450);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Requirements",
|
||||
|
@ -105,140 +35,27 @@ namespace BTCPayServer.Migrations
|
|||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (!migrationBuilder.IsSqlite())
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Requirements",
|
||||
table: "OpenIddictApplications");
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Requirements",
|
||||
table: "OpenIddictApplications");
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Subject",
|
||||
table: "OpenIddictTokens",
|
||||
maxLength: 450,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldMaxLength: 450,
|
||||
oldNullable: true);
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Subject",
|
||||
table: "OpenIddictTokens",
|
||||
maxLength: 450,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldMaxLength: 450,
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Subject",
|
||||
table: "OpenIddictAuthorizations",
|
||||
maxLength: 450,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldMaxLength: 450,
|
||||
oldNullable: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplaceOldTable(migrationBuilder, s =>
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: s,
|
||||
columns: table => new
|
||||
{
|
||||
ApplicationId = table.Column<string>(nullable: true, maxLength: null),
|
||||
AuthorizationId = table.Column<string>(nullable: true, maxLength: null),
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
CreationDate = table.Column<DateTimeOffset>(nullable: true),
|
||||
ExpirationDate = table.Column<DateTimeOffset>(nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Payload = table.Column<string>(nullable: true),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
ReferenceId = table.Column<string>(maxLength: 100, nullable: true),
|
||||
Status = table.Column<string>(maxLength: 25, nullable: false),
|
||||
Subject = table.Column<string>(maxLength: 450, nullable: false),
|
||||
Type = table.Column<string>(maxLength: 25, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictTokens", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictTokens_OpenIddictApplications_ApplicationId",
|
||||
column: x => x.ApplicationId,
|
||||
principalTable: "OpenIddictApplications",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictTokens_OpenIddictAuthorizations_AuthorizationId",
|
||||
column: x => x.AuthorizationId,
|
||||
principalTable: "OpenIddictAuthorizations",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
}, "OpenIddictTokens", "WHERE Subject IS NOT NULL");
|
||||
|
||||
ReplaceOldTable(migrationBuilder, s =>
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: s,
|
||||
columns: table => new
|
||||
{
|
||||
ApplicationId = table.Column<string>(nullable: true, maxLength: null),
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
Scopes = table.Column<string>(nullable: true),
|
||||
Status = table.Column<string>(maxLength: 25, nullable: false),
|
||||
Subject = table.Column<string>(maxLength: 450, nullable: false),
|
||||
Type = table.Column<string>(maxLength: 25, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictAuthorizations", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictAuthorizations_OpenIddictApplications_ApplicationId",
|
||||
column: x => x.ApplicationId,
|
||||
principalTable: "OpenIddictApplications",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
}, "OpenIddictAuthorizations", "WHERE Subject IS NOT NULL");
|
||||
|
||||
ReplaceOldTable(migrationBuilder, s =>
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: s,
|
||||
columns: table => new
|
||||
{
|
||||
ClientId = table.Column<string>(maxLength: 100, nullable: false),
|
||||
ClientSecret = table.Column<string>(nullable: true),
|
||||
ConcurrencyToken = table.Column<string>(maxLength: 50, nullable: true),
|
||||
ConsentType = table.Column<string>(nullable: true),
|
||||
DisplayName = table.Column<string>(nullable: true),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Permissions = table.Column<string>(nullable: true),
|
||||
PostLogoutRedirectUris = table.Column<string>(nullable: true),
|
||||
Properties = table.Column<string>(nullable: true),
|
||||
RedirectUris = table.Column<string>(nullable: true),
|
||||
Type = table.Column<string>(maxLength: 25, nullable: false),
|
||||
ApplicationUserId = table.Column<string>(nullable: true, maxLength: null)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenIddictApplications", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenIddictApplications_AspNetUsers_ApplicationUserId",
|
||||
column: x => x.ApplicationUserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
}, "OpenIddictApplications", "",
|
||||
"ClientId, ClientSecret, ConcurrencyToken, ConsentType, DisplayName, Id, Permissions, PostLogoutRedirectUris, Properties, RedirectUris, Type, ApplicationUserId");
|
||||
}
|
||||
}
|
||||
|
||||
private void ReplaceOldTable(MigrationBuilder migrationBuilder, Action<string> createTable, string tableName,
|
||||
string whereClause = "", string columns = "*")
|
||||
{
|
||||
createTable.Invoke($"New_{tableName}");
|
||||
migrationBuilder.Sql(
|
||||
$"INSERT INTO New_{tableName} {(columns == "*" ? string.Empty : $"({columns})")}SELECT {columns} FROM {tableName} {whereClause};");
|
||||
migrationBuilder.Sql("PRAGMA foreign_keys=\"0\"", true);
|
||||
migrationBuilder.Sql($"DROP TABLE {tableName}", true);
|
||||
migrationBuilder.Sql($"ALTER TABLE New_{tableName} RENAME TO {tableName}", true);
|
||||
migrationBuilder.Sql("PRAGMA foreign_keys=\"1\"", true);
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "Subject",
|
||||
table: "OpenIddictAuthorizations",
|
||||
maxLength: 450,
|
||||
nullable: false,
|
||||
oldClrType: typeof(string),
|
||||
oldMaxLength: 450,
|
||||
oldNullable: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,44 +31,37 @@ namespace BTCPayServer.Migrations
|
|||
name: "IX_ApiKeys_UserId",
|
||||
table: "ApiKeys",
|
||||
column: "UserId");
|
||||
if (this.SupportAddForeignKey(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_ApiKeys_AspNetUsers_UserId",
|
||||
table: "ApiKeys",
|
||||
column: "UserId",
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_ApiKeys_AspNetUsers_UserId",
|
||||
table: "ApiKeys",
|
||||
column: "UserId",
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (this.SupportDropForeignKey(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_ApiKeys_AspNetUsers_UserId",
|
||||
table: "ApiKeys");
|
||||
}
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_ApiKeys_AspNetUsers_UserId",
|
||||
table: "ApiKeys");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_ApiKeys_UserId",
|
||||
table: "ApiKeys");
|
||||
if (this.SupportDropColumn(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Permissions",
|
||||
table: "ApiKeys");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Type",
|
||||
table: "ApiKeys");
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Permissions",
|
||||
table: "ApiKeys");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UserId",
|
||||
table: "ApiKeys");
|
||||
}
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Type",
|
||||
table: "ApiKeys");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UserId",
|
||||
table: "ApiKeys");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,13 +26,12 @@ namespace BTCPayServer.Migrations
|
|||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OpenIddictApplications",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false, maxLength: maxLength),
|
||||
ApplicationUserId = table.Column<string>(type: "TEXT", nullable: true, maxLength: maxLength),
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false, maxLength: null),
|
||||
ApplicationUserId = table.Column<string>(type: "TEXT", nullable: true, maxLength: null),
|
||||
ClientId = table.Column<string>(type: "TEXT", maxLength: 100, nullable: false),
|
||||
ClientSecret = table.Column<string>(type: "TEXT", nullable: true),
|
||||
ConcurrencyToken = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
|
||||
|
@ -60,7 +59,7 @@ namespace BTCPayServer.Migrations
|
|||
name: "OpenIddictScopes",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false, maxLength: null),
|
||||
ConcurrencyToken = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
|
||||
Description = table.Column<string>(type: "TEXT", nullable: true),
|
||||
DisplayName = table.Column<string>(type: "TEXT", nullable: true),
|
||||
|
@ -77,8 +76,8 @@ namespace BTCPayServer.Migrations
|
|||
name: "OpenIddictAuthorizations",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false, maxLength: maxLength),
|
||||
ApplicationId = table.Column<string>(type: "TEXT", nullable: true, maxLength: maxLength),
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false, maxLength: null),
|
||||
ApplicationId = table.Column<string>(type: "TEXT", nullable: true, maxLength: null),
|
||||
ConcurrencyToken = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
|
||||
Properties = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Scopes = table.Column<string>(type: "TEXT", nullable: true),
|
||||
|
@ -101,9 +100,9 @@ namespace BTCPayServer.Migrations
|
|||
name: "OpenIddictTokens",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false, maxLength: maxLength),
|
||||
ApplicationId = table.Column<string>(type: "TEXT", nullable: true, maxLength: maxLength),
|
||||
AuthorizationId = table.Column<string>(type: "TEXT", nullable: true, maxLength: maxLength),
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false, maxLength: null),
|
||||
ApplicationId = table.Column<string>(type: "TEXT", nullable: true, maxLength: null),
|
||||
AuthorizationId = table.Column<string>(type: "TEXT", nullable: true, maxLength: null),
|
||||
ConcurrencyToken = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
|
||||
CreationDate = table.Column<DateTimeOffset>(type: "TEXT", nullable: true),
|
||||
ExpirationDate = table.Column<DateTimeOffset>(type: "TEXT", nullable: true),
|
||||
|
|
|
@ -10,12 +10,9 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (this.SupportDropColumn(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Permissions",
|
||||
table: "ApiKeys");
|
||||
}
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Permissions",
|
||||
table: "ApiKeys");
|
||||
|
||||
migrationBuilder.AddColumn<byte[]>(
|
||||
name: "Blob",
|
||||
|
@ -25,12 +22,9 @@ namespace BTCPayServer.Migrations
|
|||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (this.SupportDropColumn(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Blob",
|
||||
table: "ApiKeys");
|
||||
}
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Blob",
|
||||
table: "ApiKeys");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Permissions",
|
||||
|
|
|
@ -24,15 +24,12 @@ namespace BTCPayServer.Migrations
|
|||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (this.SupportDropColumn(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Archived",
|
||||
table: "Invoices");
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Archived",
|
||||
table: "PaymentRequests");
|
||||
}
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Archived",
|
||||
table: "Invoices");
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Archived",
|
||||
table: "PaymentRequests");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,7 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "RefundAddresses");
|
||||
|
||||
|
@ -20,7 +19,7 @@ namespace BTCPayServer.Migrations
|
|||
name: "CurrentRefundId",
|
||||
table: "Invoices",
|
||||
nullable: true,
|
||||
maxLength: maxLength);
|
||||
maxLength: null);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Notifications",
|
||||
|
@ -76,7 +75,7 @@ namespace BTCPayServer.Migrations
|
|||
PullPaymentDataId = table.Column<string>(maxLength: 30, nullable: true),
|
||||
State = table.Column<string>(maxLength: 20, nullable: false),
|
||||
PaymentMethodId = table.Column<string>(maxLength: 20, nullable: false),
|
||||
Destination = table.Column<string>(maxLength: maxLength, nullable: true),
|
||||
Destination = table.Column<string>(maxLength: null, nullable: true),
|
||||
Blob = table.Column<byte[]>(nullable: true),
|
||||
Proof = table.Column<byte[]>(nullable: true)
|
||||
},
|
||||
|
@ -95,8 +94,8 @@ namespace BTCPayServer.Migrations
|
|||
name: "Refunds",
|
||||
columns: table => new
|
||||
{
|
||||
InvoiceDataId = table.Column<string>(maxLength: maxLength, nullable: false),
|
||||
PullPaymentDataId = table.Column<string>(maxLength: maxLength, nullable: false)
|
||||
InvoiceDataId = table.Column<string>(maxLength: null, nullable: false),
|
||||
PullPaymentDataId = table.Column<string>(maxLength: null, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
@ -151,14 +150,13 @@ namespace BTCPayServer.Migrations
|
|||
table: "Refunds",
|
||||
column: "PullPaymentDataId");
|
||||
|
||||
if (this.SupportAddForeignKey(this.ActiveProvider))
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Invoices_Refunds_Id_CurrentRefundId",
|
||||
table: "Invoices",
|
||||
columns: new[] { "Id", "CurrentRefundId" },
|
||||
principalTable: "Refunds",
|
||||
principalColumns: new[] { "InvoiceDataId", "PullPaymentDataId" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Invoices_Refunds_Id_CurrentRefundId",
|
||||
table: "Invoices",
|
||||
columns: new[] { "Id", "CurrentRefundId" },
|
||||
principalTable: "Refunds",
|
||||
principalColumns: new[] { "InvoiceDataId", "PullPaymentDataId" },
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
|
|
|
@ -20,13 +20,9 @@ namespace BTCPayServer.Migrations
|
|||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (this.SupportDropColumn(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Severity",
|
||||
table: "InvoiceEvents");
|
||||
|
||||
}
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Severity",
|
||||
table: "InvoiceEvents");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,13 +19,9 @@ namespace BTCPayServer.Migrations
|
|||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (this.SupportDropColumn(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Created",
|
||||
table: "AspNetUsers");
|
||||
|
||||
}
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Created",
|
||||
table: "AspNetUsers");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,38 +10,32 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (this.SupportDropForeignKey(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_U2FDevices_AspNetUsers_ApplicationUserId",
|
||||
table: "U2FDevices");
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_U2FDevices_AspNetUsers_ApplicationUserId",
|
||||
table: "U2FDevices");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_U2FDevices_AspNetUsers_ApplicationUserId",
|
||||
table: "U2FDevices",
|
||||
column: "ApplicationUserId",
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_U2FDevices_AspNetUsers_ApplicationUserId",
|
||||
table: "U2FDevices",
|
||||
column: "ApplicationUserId",
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (this.SupportDropForeignKey(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_U2FDevices_AspNetUsers_ApplicationUserId",
|
||||
table: "U2FDevices");
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_U2FDevices_AspNetUsers_ApplicationUserId",
|
||||
table: "U2FDevices");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_U2FDevices_AspNetUsers_ApplicationUserId",
|
||||
table: "U2FDevices",
|
||||
column: "ApplicationUserId",
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_U2FDevices_AspNetUsers_ApplicationUserId",
|
||||
table: "U2FDevices",
|
||||
column: "ApplicationUserId",
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,15 +10,12 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (!migrationBuilder.IsSqlite())
|
||||
{
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "OrderId",
|
||||
table: "Invoices",
|
||||
maxLength: 100,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string));
|
||||
}
|
||||
migrationBuilder.AlterColumn<string>(
|
||||
name: "OrderId",
|
||||
table: "Invoices",
|
||||
maxLength: 100,
|
||||
nullable: true,
|
||||
oldClrType: typeof(string));
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Invoices_OrderId",
|
||||
|
|
|
@ -11,14 +11,13 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Fido2Credentials",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Name = table.Column<string>(nullable: true),
|
||||
ApplicationUserId = table.Column<string>(nullable: true, maxLength: maxLength),
|
||||
ApplicationUserId = table.Column<string>(nullable: true, maxLength: null),
|
||||
Blob = table.Column<byte[]>(nullable: true),
|
||||
Type = table.Column<int>(nullable: false)
|
||||
},
|
||||
|
|
|
@ -17,19 +17,18 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "StoreDataId",
|
||||
table: "Payouts",
|
||||
nullable: true,
|
||||
maxLength: maxLength);
|
||||
name: "StoreDataId",
|
||||
table: "Payouts",
|
||||
nullable: true,
|
||||
maxLength: null);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PayoutProcessors",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
StoreId = table.Column<string>(nullable: true, maxLength: maxLength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
StoreId = table.Column<string>(nullable: true, maxLength: null),
|
||||
PaymentMethod = table.Column<string>(nullable: true),
|
||||
Processor = table.Column<string>(nullable: true),
|
||||
Blob = table.Column<byte[]>(nullable: true)
|
||||
|
@ -54,40 +53,31 @@ namespace BTCPayServer.Migrations
|
|||
name: "IX_PayoutProcessors_StoreId",
|
||||
table: "PayoutProcessors",
|
||||
column: "StoreId");
|
||||
if (this.SupportAddForeignKey(ActiveProvider))
|
||||
{
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Payouts_Stores_StoreDataId",
|
||||
table: "Payouts",
|
||||
column: "StoreDataId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Payouts_Stores_StoreDataId",
|
||||
table: "Payouts",
|
||||
column: "StoreDataId",
|
||||
principalTable: "Stores",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (this.SupportDropForeignKey(ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Payouts_Stores_StoreDataId",
|
||||
table: "Payouts");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Payouts_Stores_StoreDataId",
|
||||
table: "Payouts");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "PayoutProcessors");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Payouts_StoreDataId",
|
||||
table: "Payouts");
|
||||
}
|
||||
if(this.SupportDropColumn(ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "StoreDataId",
|
||||
table: "Payouts");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,12 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxLength = this.IsMySql(migrationBuilder.ActiveProvider) ? (int?)255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
migrationBuilder.CreateTable(
|
||||
name: "LightningAddresses",
|
||||
columns: table => new
|
||||
{
|
||||
Username = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
StoreDataId = table.Column<string>(nullable: false, maxLength: maxLength),
|
||||
Username = table.Column<string>(nullable: false, maxLength: null),
|
||||
StoreDataId = table.Column<string>(nullable: false, maxLength: null),
|
||||
Blob = table.Column<byte[]>( nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
|
|
|
@ -14,14 +14,13 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxlength = migrationBuilder.IsMySql() ? 255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
name: "StoreSettings",
|
||||
columns: table => new
|
||||
{
|
||||
Name = table.Column<string>(nullable: false, maxLength: maxlength),
|
||||
StoreId = table.Column<string>(nullable: false, maxLength: maxlength),
|
||||
Value = table.Column<string>(type: migrationBuilder.IsNpgsql() ? "JSONB" : "TEXT", nullable: true)
|
||||
Name = table.Column<string>(nullable: false, maxLength: null),
|
||||
StoreId = table.Column<string>(nullable: false, maxLength: null),
|
||||
Value = table.Column<string>(type: "JSONB", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
|
|
@ -17,16 +17,14 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxlength = migrationBuilder.IsMySql() ? 255 : null;
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "WalletObjects",
|
||||
columns: table => new
|
||||
{
|
||||
WalletId = table.Column<string>(nullable: false, maxLength: maxlength),
|
||||
Type = table.Column<string>(nullable: false, maxLength: maxlength),
|
||||
Id = table.Column<string>(nullable: false, maxLength: maxlength),
|
||||
Data = table.Column<string>(type: migrationBuilder.IsNpgsql() ? "JSONB" : "TEXT", nullable: true)
|
||||
WalletId = table.Column<string>(nullable: false, maxLength: null),
|
||||
Type = table.Column<string>(nullable: false, maxLength: null),
|
||||
Id = table.Column<string>(nullable: false, maxLength: null),
|
||||
Data = table.Column<string>(type: "JSONB", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
@ -37,18 +35,16 @@ namespace BTCPayServer.Migrations
|
|||
table: "WalletObjects",
|
||||
columns: new[] { "Type", "Id" });
|
||||
|
||||
|
||||
maxlength = migrationBuilder.IsMySql() ? 100 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
name: "WalletObjectLinks",
|
||||
columns: table => new
|
||||
{
|
||||
WalletId = table.Column<string>(nullable: false, maxLength: maxlength),
|
||||
AType = table.Column<string>(nullable: false, maxLength: maxlength),
|
||||
AId = table.Column<string>(nullable: false, maxLength: maxlength),
|
||||
BType = table.Column<string>(nullable: false, maxLength: maxlength),
|
||||
BId = table.Column<string>(nullable: false, maxLength: maxlength),
|
||||
Data = table.Column<string>(type: migrationBuilder.IsNpgsql() ? "JSONB" : "TEXT", nullable: true)
|
||||
WalletId = table.Column<string>(nullable: false, maxLength: null),
|
||||
AType = table.Column<string>(nullable: false, maxLength: null),
|
||||
AId = table.Column<string>(nullable: false, maxLength: null),
|
||||
BType = table.Column<string>(nullable: false, maxLength: null),
|
||||
BId = table.Column<string>(nullable: false, maxLength: null),
|
||||
Data = table.Column<string>(type: "JSONB", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
|
|
@ -16,11 +16,8 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (migrationBuilder.IsNpgsql())
|
||||
{
|
||||
migrationBuilder.Sql("ALTER TABLE \"Settings\" ALTER COLUMN \"Value\" TYPE JSONB USING \"Value\"::JSONB");
|
||||
migrationBuilder.Sql("ALTER TABLE \"Stores\" ALTER COLUMN \"StoreBlob\" TYPE JSONB USING regexp_replace(convert_from(\"StoreBlob\",'UTF8'), '\\\\u0000', '', 'g')::JSONB");
|
||||
}
|
||||
migrationBuilder.Sql("ALTER TABLE \"Settings\" ALTER COLUMN \"Value\" TYPE JSONB USING \"Value\"::JSONB");
|
||||
migrationBuilder.Sql("ALTER TABLE \"Stores\" ALTER COLUMN \"StoreBlob\" TYPE JSONB USING regexp_replace(convert_from(\"StoreBlob\",'UTF8'), '\\\\u0000', '', 'g')::JSONB");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
|
|
|
@ -16,10 +16,7 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (migrationBuilder.IsNpgsql())
|
||||
{
|
||||
migrationBuilder.Sql("UPDATE \"Stores\" SET \"StoreBlob\"=jsonb_set(\"StoreBlob\", \'{preferredExchange}\', \'{\"oasis_trade\": \"oasisdev\", \"gdax\":\"coinbasepro\", \"coinaverage\":\"coingecko\"}\'::jsonb->(\"StoreBlob\"->>\'preferredExchange\')) WHERE \"StoreBlob\"->>\'preferredExchange\' = ANY (ARRAY[\'oasis_trade\', \'gdax\', \'coinaverage\']);");
|
||||
}
|
||||
migrationBuilder.Sql("UPDATE \"Stores\" SET \"StoreBlob\"=jsonb_set(\"StoreBlob\", \'{preferredExchange}\', \'{\"oasis_trade\": \"oasisdev\", \"gdax\":\"coinbasepro\", \"coinaverage\":\"coingecko\"}\'::jsonb->(\"StoreBlob\"->>\'preferredExchange\')) WHERE \"StoreBlob\"->>\'preferredExchange\' = ANY (ARRAY[\'oasis_trade\', \'gdax\', \'coinaverage\']);");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
|
|
|
@ -16,15 +16,14 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
int? maxlength = migrationBuilder.IsMySql() ? 255 : null;
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Forms",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false, maxLength: maxlength),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: true, maxLength: maxlength),
|
||||
StoreId = table.Column<string>(type: "TEXT", nullable: true, maxLength: maxlength),
|
||||
Config = table.Column<string>(type: migrationBuilder.IsNpgsql() ? "JSONB" : "TEXT", nullable: true),
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false, maxLength: null),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: true, maxLength: null),
|
||||
StoreId = table.Column<string>(type: "TEXT", nullable: true, maxLength: null),
|
||||
Config = table.Column<string>(type: "JSONB", nullable: true),
|
||||
Public = table.Column<bool>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
|
|
|
@ -14,76 +14,75 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
var type = migrationBuilder.IsNpgsql() ? "JSONB" : "TEXT";
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Blob2",
|
||||
table: "Webhooks",
|
||||
type: type,
|
||||
type: "JSONB",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Blob2",
|
||||
table: "WebhookDeliveries",
|
||||
type: type,
|
||||
type: "JSONB",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Blob2",
|
||||
table: "PaymentRequests",
|
||||
type: type,
|
||||
type: "JSONB",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Blob2",
|
||||
table: "Notifications",
|
||||
type: type,
|
||||
type: "JSONB",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Blob2",
|
||||
table: "LightningAddresses",
|
||||
type: type,
|
||||
type: "JSONB",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Blob2",
|
||||
table: "Fido2Credentials",
|
||||
type: type,
|
||||
type: "JSONB",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Blob2",
|
||||
table: "AspNetUsers",
|
||||
type: type,
|
||||
type: "JSONB",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Blob2",
|
||||
table: "ApiKeys",
|
||||
type: type,
|
||||
type: "JSONB",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Blob2",
|
||||
table: "Invoices",
|
||||
type: type,
|
||||
type: "JSONB",
|
||||
nullable: true);
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Blob2",
|
||||
table: "Payments",
|
||||
type: type,
|
||||
type: "JSONB",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Blob2",
|
||||
table: "PayoutProcessors",
|
||||
type: type,
|
||||
type: "JSONB",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Blob2",
|
||||
table: "CustodianAccount",
|
||||
type: type,
|
||||
type: "JSONB",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
|
|
|
@ -16,10 +16,7 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (migrationBuilder.IsNpgsql())
|
||||
{
|
||||
migrationBuilder.Sql("ALTER TABLE \"Stores\" ALTER COLUMN \"DerivationStrategies\" TYPE JSONB USING \"DerivationStrategies\"::JSONB");
|
||||
}
|
||||
migrationBuilder.Sql("ALTER TABLE \"Stores\" ALTER COLUMN \"DerivationStrategies\" TYPE JSONB USING \"DerivationStrategies\"::JSONB");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
|
|
|
@ -16,11 +16,8 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (migrationBuilder.IsNpgsql())
|
||||
{
|
||||
migrationBuilder.Sql("ALTER TABLE \"InvoiceSearches\" ALTER COLUMN \"Value\" TYPE TEXT USING \"Value\"::TEXT;");
|
||||
migrationBuilder.Sql("ALTER TABLE \"Invoices\" ALTER COLUMN \"OrderId\" TYPE TEXT USING \"OrderId\"::TEXT;");
|
||||
}
|
||||
migrationBuilder.Sql("ALTER TABLE \"InvoiceSearches\" ALTER COLUMN \"Value\" TYPE TEXT USING \"Value\"::TEXT;");
|
||||
migrationBuilder.Sql("ALTER TABLE \"Invoices\" ALTER COLUMN \"OrderId\" TYPE TEXT USING \"OrderId\"::TEXT;");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
|
|
|
@ -17,7 +17,6 @@ namespace BTCPayServer.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
var permissionsType = migrationBuilder.IsNpgsql() ? "TEXT[]" : "TEXT";
|
||||
migrationBuilder.CreateTable(
|
||||
name: "StoreRoles",
|
||||
columns: table => new
|
||||
|
@ -25,7 +24,7 @@ namespace BTCPayServer.Migrations
|
|||
Id = table.Column<string>(type: "TEXT", nullable: false),
|
||||
StoreDataId = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Role = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Permissions = table.Column<string>(type: permissionsType, nullable: false)
|
||||
Permissions = table.Column<string>(type: "TEXT[]", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
@ -44,60 +43,45 @@ namespace BTCPayServer.Migrations
|
|||
columns: new[] { "StoreDataId", "Role" },
|
||||
unique: true);
|
||||
|
||||
object GetPermissionsData(string[] permissions)
|
||||
{
|
||||
if (migrationBuilder.IsNpgsql())
|
||||
return permissions;
|
||||
return JsonConvert.SerializeObject(permissions);
|
||||
}
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
"StoreRoles",
|
||||
columns: new[] { "Id", "Role", "Permissions" },
|
||||
columnTypes: new[] { "TEXT", "TEXT", permissionsType },
|
||||
columnTypes: new[] { "TEXT", "TEXT", "TEXT[]" },
|
||||
values: new object[,]
|
||||
{
|
||||
{
|
||||
"Owner", "Owner", GetPermissionsData(new[]
|
||||
"Owner", "Owner", new[]
|
||||
{
|
||||
"btcpay.store.canmodifystoresettings",
|
||||
"btcpay.store.cantradecustodianaccount",
|
||||
"btcpay.store.canwithdrawfromcustodianaccount",
|
||||
"btcpay.store.candeposittocustodianaccount"
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
"Guest", "Guest", GetPermissionsData(new[]
|
||||
"Guest", "Guest", new[]
|
||||
{
|
||||
"btcpay.store.canviewstoresettings",
|
||||
"btcpay.store.canmodifyinvoices",
|
||||
"btcpay.store.canviewcustodianaccounts",
|
||||
"btcpay.store.candeposittocustodianaccount"
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (this.SupportAddForeignKey(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_UserStore_StoreRoles_Role",
|
||||
table: "UserStore",
|
||||
column: "Role",
|
||||
principalTable: "StoreRoles",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_UserStore_StoreRoles_Role",
|
||||
table: "UserStore",
|
||||
column: "Role",
|
||||
principalTable: "StoreRoles",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
if (this.SupportDropForeignKey(migrationBuilder.ActiveProvider))
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_UserStore_StoreRoles_Role",
|
||||
table: "UserStore");
|
||||
}
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_UserStore_StoreRoles_Role",
|
||||
table: "UserStore");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "StoreRoles");
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,28 +0,0 @@
|
|||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
public static class MigrationsExtensions
|
||||
{
|
||||
public static bool SupportDropColumn(this Microsoft.EntityFrameworkCore.Migrations.Migration migration, string activeProvider)
|
||||
{
|
||||
return activeProvider != "Microsoft.EntityFrameworkCore.Sqlite";
|
||||
}
|
||||
public static bool SupportAddForeignKey(this Microsoft.EntityFrameworkCore.Migrations.Migration migration, string activeProvider)
|
||||
{
|
||||
return activeProvider != "Microsoft.EntityFrameworkCore.Sqlite";
|
||||
}
|
||||
public static bool SupportDropForeignKey(this Microsoft.EntityFrameworkCore.Migrations.Migration migration, string activeProvider)
|
||||
{
|
||||
return activeProvider != "Microsoft.EntityFrameworkCore.Sqlite";
|
||||
}
|
||||
public static bool SupportDropForeignKey(this DatabaseFacade facade)
|
||||
{
|
||||
return facade.ProviderName != "Microsoft.EntityFrameworkCore.Sqlite";
|
||||
}
|
||||
public static bool IsMySql(this Microsoft.EntityFrameworkCore.Migrations.Migration migration, string activeProvider)
|
||||
{
|
||||
return activeProvider == "Pomelo.EntityFrameworkCore.MySql";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1270,17 +1270,6 @@ bc1qfzu57kgu5jthl934f9xrdzzx8mmemx7gn07tf0grnvz504j6kzusu2v0ku
|
|||
Assert.Contains("originalDeliveryId", serialized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanCreateSqlitedb()
|
||||
{
|
||||
if (File.Exists("temp.db"))
|
||||
File.Delete("temp.db");
|
||||
// This test sqlite can migrate
|
||||
var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
|
||||
builder.UseSqlite("Data Source=temp.db");
|
||||
await new ApplicationDbContext(builder.Options).Database.MigrateAsync();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanUsePermission()
|
||||
{
|
||||
|
|
|
@ -4179,20 +4179,20 @@ namespace BTCPayServer.Tests
|
|||
Assert.Single(testObj.Links.Where(l => l.Id == "test1" && l.LinkData["testData"]?.Value<string>() == "lol"));
|
||||
Assert.Single(testObj.Links.Where(l => l.Id == "test1" && l.ObjectData is null));
|
||||
|
||||
async Task TestWalletRepository(bool useInefficient)
|
||||
async Task TestWalletRepository()
|
||||
{
|
||||
// We should have 4 nodes, two `test` type and one `newtype`
|
||||
// Only the node `test` `test` is connected to `test1`
|
||||
var wid = new WalletId(admin.StoreId, "BTC");
|
||||
var repo = tester.PayTester.GetService<WalletRepository>();
|
||||
var allObjects = await repo.GetWalletObjects(new(wid) { UseInefficientPath = useInefficient });
|
||||
var allObjectsNoWallet = await repo.GetWalletObjects((new() { UseInefficientPath = useInefficient }));
|
||||
var allObjectsNoWalletAndType = await repo.GetWalletObjects((new() { Type = "test", UseInefficientPath = useInefficient }));
|
||||
var allTests = await repo.GetWalletObjects((new(wid, "test") { UseInefficientPath = useInefficient }));
|
||||
var twoTests2 = await repo.GetWalletObjects((new(wid, "test", new[] { "test1", "test2", "test-unk" }) { UseInefficientPath = useInefficient }));
|
||||
var oneTest = await repo.GetWalletObjects((new(wid, "test", new[] { "test" }) { UseInefficientPath = useInefficient }));
|
||||
var oneTestWithoutData = await repo.GetWalletObjects((new(wid, "test", new[] { "test" }) { UseInefficientPath = useInefficient, IncludeNeighbours = false }));
|
||||
var idsTypes = await repo.GetWalletObjects((new(wid) { TypesIds = new[] { new ObjectTypeId("test", "test1"), new ObjectTypeId("test", "test2") }, UseInefficientPath = useInefficient }));
|
||||
var allObjects = await repo.GetWalletObjects(new(wid));
|
||||
var allObjectsNoWallet = await repo.GetWalletObjects((new()));
|
||||
var allObjectsNoWalletAndType = await repo.GetWalletObjects((new() { Type = "test" }));
|
||||
var allTests = await repo.GetWalletObjects((new(wid, "test")));
|
||||
var twoTests2 = await repo.GetWalletObjects((new(wid, "test", new[] { "test1", "test2", "test-unk" })));
|
||||
var oneTest = await repo.GetWalletObjects((new(wid, "test", new[] { "test" })));
|
||||
var oneTestWithoutData = await repo.GetWalletObjects((new(wid, "test", new[] { "test" }) { IncludeNeighbours = false }));
|
||||
var idsTypes = await repo.GetWalletObjects((new(wid) { TypesIds = new[] { new ObjectTypeId("test", "test1"), new ObjectTypeId("test", "test2") }}));
|
||||
|
||||
Assert.Equal(4, allObjects.Count);
|
||||
// We are reusing a db in this test, as such we may have other wallets here.
|
||||
|
@ -4206,8 +4206,7 @@ namespace BTCPayServer.Tests
|
|||
Assert.Null(oneTestWithoutData.First().Value.GetNeighbours().Select(n => n.Data).FirstOrDefault());
|
||||
Assert.Equal(2, idsTypes.Count);
|
||||
}
|
||||
await TestWalletRepository(false);
|
||||
await TestWalletRepository(true);
|
||||
await TestWalletRepository();
|
||||
|
||||
{
|
||||
var allObjects = await client.GetOnChainWalletObjects(admin.StoreId, "BTC");
|
||||
|
|
|
@ -36,9 +36,7 @@ namespace BTCPayServer.Configuration
|
|||
app.Option("--signet | -signet", $"Use signet (deprecated, use --network instead)", CommandOptionType.BoolValue);
|
||||
app.Option("--chains | -c", $"Chains to support as a comma separated (default: btc; available: {chains})", CommandOptionType.SingleValue);
|
||||
app.Option("--postgres", $"Connection string to a PostgreSQL database", CommandOptionType.SingleValue);
|
||||
app.Option("--mysql", $"DEPRECATED: Connection string to a MySQL database", CommandOptionType.SingleValue);
|
||||
app.Option("--nocsp", $"Disable CSP (default false)", CommandOptionType.BoolValue);
|
||||
app.Option("--sqlitefile", $"DEPRECATED: File name to an SQLite database file inside the data directory", CommandOptionType.SingleValue);
|
||||
app.Option("--deprecated", $"Allow deprecated settings (default:false)", CommandOptionType.BoolValue);
|
||||
app.Option("--externalservices", $"Links added to external services inside Server Settings / Services under the format service1:path2;service2:path2.(default: empty)", CommandOptionType.SingleValue);
|
||||
app.Option("--rootpath", "The root path in the URL to access BTCPay (default: /)", CommandOptionType.SingleValue);
|
||||
|
@ -139,8 +137,6 @@ namespace BTCPayServer.Configuration
|
|||
builder.AppendLine();
|
||||
builder.AppendLine("### Database ###");
|
||||
builder.AppendLine("#postgres=User ID=root;Password=myPassword;Host=localhost;Port=5432;Database=myDataBase;");
|
||||
builder.AppendLine("#mysql=User ID=root;Password=myPassword;Host=localhost;Port=3306;Database=myDataBase;");
|
||||
builder.AppendLine("#sqlitefile=sqlite.db");
|
||||
builder.AppendLine();
|
||||
builder.AppendLine("### NBXplorer settings ###");
|
||||
foreach (var n in CreateBTCPayNetworkProvider(networkType).GetAll().OfType<BTCPayNetwork>())
|
||||
|
|
|
@ -63,12 +63,6 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||
{
|
||||
return StoreNotFound();
|
||||
}
|
||||
|
||||
if (!_storeRepository.CanDeleteStores())
|
||||
{
|
||||
return this.CreateAPIError("unsupported",
|
||||
"BTCPay Server is using a database server that does not allow you to remove stores.");
|
||||
}
|
||||
await _storeRepository.RemoveStore(storeId, _userManager.GetUserId(User));
|
||||
return Ok();
|
||||
}
|
||||
|
|
|
@ -40,8 +40,7 @@ public partial class UIStoresController
|
|||
InvoiceExpiration = (int)storeBlob.InvoiceExpiration.TotalMinutes,
|
||||
DefaultCurrency = storeBlob.DefaultCurrency,
|
||||
BOLT11Expiration = (long)storeBlob.RefundBOLT11Expiration.TotalDays,
|
||||
Archived = store.Archived,
|
||||
CanDelete = _storeRepo.CanDeleteStores()
|
||||
Archived = store.Archived
|
||||
};
|
||||
|
||||
return View(vm);
|
||||
|
|
|
@ -24,8 +24,6 @@ namespace BTCPayServer.HostedServices
|
|||
public async Task Do(CancellationToken cancellationToken)
|
||||
{
|
||||
await using var ctx = DbContextFactory.CreateContext();
|
||||
if (!ctx.Database.IsNpgsql())
|
||||
return;
|
||||
var conn = ctx.Database.GetDbConnection();
|
||||
bool pruned = false;
|
||||
int offset = 0;
|
||||
|
|
|
@ -145,9 +145,7 @@ namespace BTCPayServer.Hosting
|
|||
services.TryAddSingleton<InvoicePaymentNotification>();
|
||||
services.TryAddSingleton<BTCPayServerOptions>(o =>
|
||||
o.GetRequiredService<IOptions<BTCPayServerOptions>>().Value);
|
||||
// Don't move this StartupTask, we depend on it being right here
|
||||
if (configuration["POSTGRES"] != null && (configuration["SQLITEFILE"] != null || configuration["MYSQL"] != null))
|
||||
services.AddStartupTask<ToPostgresMigrationStartupTask>();
|
||||
|
||||
services.AddStartupTask<MigrationStartupTask>();
|
||||
|
||||
//
|
||||
|
@ -184,24 +182,10 @@ namespace BTCPayServer.Hosting
|
|||
(options, datadirs) =>
|
||||
{
|
||||
var postgresConnectionString = configuration["postgres"];
|
||||
var mySQLConnectionString = configuration["mysql"];
|
||||
var sqliteFileName = configuration["sqlitefile"];
|
||||
|
||||
if (!string.IsNullOrEmpty(postgresConnectionString))
|
||||
{
|
||||
options.DatabaseType = DatabaseType.Postgres;
|
||||
options.ConnectionString = postgresConnectionString;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(mySQLConnectionString))
|
||||
{
|
||||
options.DatabaseType = DatabaseType.MySQL;
|
||||
options.ConnectionString = mySQLConnectionString;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(sqliteFileName))
|
||||
{
|
||||
options.DatabaseType = DatabaseType.Sqlite;
|
||||
options.ConnectionString = "Data Source=" + datadirs.Value.ToDatadirFullPath(sqliteFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("No database option was configured.");
|
||||
|
|
|
@ -372,12 +372,21 @@ namespace BTCPayServer.Hosting
|
|||
private async Task FixSeqAfterSqliteMigration()
|
||||
{
|
||||
await using var ctx = _DBContextFactory.CreateContext();
|
||||
if (!ctx.Database.IsNpgsql())
|
||||
return;
|
||||
var state = await ToPostgresMigrationStartupTask.GetMigrationState(ctx);
|
||||
var state = await GetMigrationState(ctx);
|
||||
if (state != "complete")
|
||||
return;
|
||||
await ToPostgresMigrationStartupTask.UpdateSequenceInvoiceSearch(ctx);
|
||||
await UpdateSequenceInvoiceSearch(ctx);
|
||||
}
|
||||
static async Task<string> GetMigrationState(ApplicationDbContext postgresContext)
|
||||
{
|
||||
var o = (await postgresContext.Settings.FromSqlRaw("SELECT \"Id\", \"Value\" FROM \"Settings\" WHERE \"Id\"='MigrationData'").AsNoTracking().FirstOrDefaultAsync())?.Value;
|
||||
if (o is null)
|
||||
return null;
|
||||
return JObject.Parse(o)["state"]?.Value<string>();
|
||||
}
|
||||
static async Task UpdateSequenceInvoiceSearch(ApplicationDbContext postgresContext)
|
||||
{
|
||||
await postgresContext.Database.ExecuteSqlRawAsync("SELECT SETVAL('\"InvoiceSearches_Id_seq\"', (SELECT max(\"Id\") FROM \"InvoiceSearches\"));");
|
||||
}
|
||||
private async Task MigrateAppYmlToJson()
|
||||
{
|
||||
|
@ -646,9 +655,7 @@ namespace BTCPayServer.Hosting
|
|||
{
|
||||
await using var ctx = _DBContextFactory.CreateContext();
|
||||
|
||||
if (ctx.Database.IsNpgsql())
|
||||
{
|
||||
await ctx.Database.ExecuteSqlRawAsync(@"
|
||||
await ctx.Database.ExecuteSqlRawAsync(@"
|
||||
WITH cte AS (
|
||||
SELECT DISTINCT p.""Id"", pp.""StoreId"" FROM ""Payouts"" p
|
||||
JOIN ""PullPayments"" pp ON pp.""Id"" = p.""PullPaymentDataId""
|
||||
|
@ -659,22 +666,6 @@ SET ""StoreDataId""=cte.""StoreId""
|
|||
FROM cte
|
||||
WHERE cte.""Id""=p.""Id""
|
||||
");
|
||||
}
|
||||
else
|
||||
{
|
||||
var queryable = ctx.Payouts.Where(data => data.StoreDataId == null);
|
||||
var count = await queryable.CountAsync();
|
||||
_logger.LogInformation($"Migrating {count} payouts to have a store id explicitly");
|
||||
for (int i = 0; i < count; i += 1000)
|
||||
{
|
||||
await queryable.Include(data => data.PullPaymentData).Skip(i).Take(1000)
|
||||
.ForEachAsync(data => data.StoreDataId = data.PullPaymentData.StoreId);
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
_logger.LogInformation($"Migrated {i + 1000}/{count} payouts to have a store id explicitly");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task AddInitialUserBlob()
|
||||
|
@ -944,11 +935,6 @@ retry:
|
|||
{
|
||||
var db = _DBContextFactory.CreateContext();
|
||||
await db.Database.MigrateAsync();
|
||||
if (db.Database.IsNpgsql())
|
||||
{
|
||||
if (await db.GetMigrationState() == "pending")
|
||||
throw new ConfigException("This database hasn't been completely migrated, please retry migration by setting the BTCPAY_SQLITEFILE or BTCPAY_MYSQL setting on top of BTCPAY_POSTGRES");
|
||||
}
|
||||
}
|
||||
// Starting up
|
||||
catch (ConfigException) { throw; }
|
||||
|
|
|
@ -1,296 +0,0 @@
|
|||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Amazon.Runtime.Internal.Util;
|
||||
using AngleSharp.Text;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Configuration;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MySqlConnector;
|
||||
using NBXplorer;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Npgsql;
|
||||
|
||||
namespace BTCPayServer.Hosting
|
||||
{
|
||||
static class TopologySort
|
||||
{
|
||||
public static IEnumerable<ITable> OrderByTopology(this IEnumerable<ITable> tables)
|
||||
{
|
||||
var comparer = Comparer<ITable>.Create((a, b) => a.Name.CompareTo(b.Name));
|
||||
return OrderByTopology(
|
||||
tables,
|
||||
t =>
|
||||
{
|
||||
if (t.Name == "Invoices")
|
||||
return t.ForeignKeyConstraints.Select(f => f.PrincipalTable.Name).Where(f => f != "Refunds");
|
||||
else
|
||||
return t.ForeignKeyConstraints.Select(f => f.PrincipalTable.Name);
|
||||
},
|
||||
t => t.Name,
|
||||
t => t,
|
||||
comparer);
|
||||
}
|
||||
public static IEnumerable<TValue> OrderByTopology<T, TDepend, TValue>(
|
||||
this IEnumerable<T> values,
|
||||
Func<T, IEnumerable<TDepend>> dependsOn,
|
||||
Func<T, TDepend> getKey,
|
||||
Func<T, TValue> getValue,
|
||||
IComparer<T>? solveTies = null) where T : notnull
|
||||
{
|
||||
var v = values.ToList();
|
||||
return TopologicalSort(v, dependsOn, getKey, getValue, solveTies);
|
||||
}
|
||||
|
||||
static List<TValue> TopologicalSort<T, TDepend, TValue>(this IReadOnlyCollection<T> nodes,
|
||||
Func<T, IEnumerable<TDepend>> dependsOn,
|
||||
Func<T, TDepend> getKey,
|
||||
Func<T, TValue> getValue,
|
||||
IComparer<T>? solveTies = null) where T : notnull
|
||||
{
|
||||
if (nodes.Count == 0)
|
||||
return new List<TValue>();
|
||||
if (getKey == null)
|
||||
throw new ArgumentNullException(nameof(getKey));
|
||||
if (getValue == null)
|
||||
throw new ArgumentNullException(nameof(getValue));
|
||||
solveTies = solveTies ?? Comparer<T>.Default;
|
||||
List<TValue> result = new List<TValue>(nodes.Count);
|
||||
HashSet<TDepend> allKeys = new HashSet<TDepend>(nodes.Count);
|
||||
var noDependencies = new SortedDictionary<T, HashSet<TDepend>>(solveTies);
|
||||
|
||||
foreach (var node in nodes)
|
||||
allKeys.Add(getKey(node));
|
||||
var dependenciesByValues = nodes.ToDictionary(node => node,
|
||||
node => new HashSet<TDepend>(dependsOn(node).Where(n => allKeys.Contains(n))));
|
||||
foreach (var e in dependenciesByValues.Where(x => x.Value.Count == 0))
|
||||
{
|
||||
noDependencies.Add(e.Key, e.Value);
|
||||
}
|
||||
if (noDependencies.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Impossible to topologically sort a cyclic graph");
|
||||
}
|
||||
while (noDependencies.Count > 0)
|
||||
{
|
||||
var nodep = noDependencies.First();
|
||||
noDependencies.Remove(nodep.Key);
|
||||
dependenciesByValues.Remove(nodep.Key);
|
||||
|
||||
var elemKey = getKey(nodep.Key);
|
||||
result.Add(getValue(nodep.Key));
|
||||
foreach (var selem in dependenciesByValues)
|
||||
{
|
||||
if (selem.Value.Remove(elemKey) && selem.Value.Count == 0)
|
||||
noDependencies.Add(selem.Key, selem.Value);
|
||||
}
|
||||
}
|
||||
if (dependenciesByValues.Count != 0)
|
||||
{
|
||||
throw new InvalidOperationException("Impossible to topologically sort a cyclic graph");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
public class ToPostgresMigrationStartupTask : IStartupTask
|
||||
{
|
||||
|
||||
public ToPostgresMigrationStartupTask(
|
||||
IConfiguration configuration,
|
||||
IOptions<DataDirectories> datadirs,
|
||||
ILogger<ToPostgresMigrationStartupTask> logger,
|
||||
IWebHostEnvironment environment,
|
||||
ApplicationDbContextFactory dbContextFactory)
|
||||
{
|
||||
Configuration = configuration;
|
||||
Datadirs = datadirs;
|
||||
Logger = logger;
|
||||
Environment = environment;
|
||||
DbContextFactory = dbContextFactory;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
public IOptions<DataDirectories> Datadirs { get; }
|
||||
public ILogger<ToPostgresMigrationStartupTask> Logger { get; }
|
||||
public IWebHostEnvironment Environment { get; }
|
||||
public ApplicationDbContextFactory DbContextFactory { get; }
|
||||
public bool HasError { get; private set; }
|
||||
|
||||
public async Task ExecuteAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var p = Configuration.GetOrDefault<string?>("POSTGRES", null);
|
||||
var sqlite = Configuration.GetOrDefault<string?>("SQLITEFILE", null);
|
||||
var mysql = Configuration.GetOrDefault<string?>("MYSQL", null);
|
||||
|
||||
string migratingFrom;
|
||||
ApplicationDbContext otherContext;
|
||||
if (string.IsNullOrEmpty(p))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(sqlite))
|
||||
{
|
||||
migratingFrom = "SQLite";
|
||||
sqlite = Datadirs.Value.ToDatadirFullPath(sqlite);
|
||||
if (!File.Exists(sqlite))
|
||||
return;
|
||||
otherContext = new ApplicationDbContext(new DbContextOptionsBuilder<ApplicationDbContext>().UseSqlite("Data Source=" + sqlite, o => o.CommandTimeout(60 * 60 * 10)).Options);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(mysql))
|
||||
{
|
||||
migratingFrom = "MySQL";
|
||||
otherContext = new ApplicationDbContext(new DbContextOptionsBuilder<ApplicationDbContext>().UseMySql(mysql, ServerVersion.AutoDetect(mysql), o => o.CommandTimeout(60 * 60 * 10)).Options);
|
||||
try
|
||||
{
|
||||
await otherContext.Settings.FirstOrDefaultAsync();
|
||||
}
|
||||
catch (MySqlException ex) when (ex.SqlState == "42000") // DB doesn't exists
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (await otherContext.Settings.FirstOrDefaultAsync() == null)
|
||||
return;
|
||||
{
|
||||
using var postgresContext = new ApplicationDbContext(new DbContextOptionsBuilder<ApplicationDbContext>().UseNpgsql(p, o =>
|
||||
{
|
||||
o.CommandTimeout(60 * 60 * 10);
|
||||
o.SetPostgresVersion(12, 0);
|
||||
}).Options);
|
||||
string? state;
|
||||
try
|
||||
{
|
||||
state = await GetMigrationState(postgresContext);
|
||||
if (state == "complete")
|
||||
return;
|
||||
if (state == null)
|
||||
throw new ConfigException("This postgres database isn't created during a migration. Please use an empty database for postgres when migrating. If it's not a migration, remove --sqlitefile or --mysql settings.");
|
||||
}
|
||||
catch (NpgsqlException ex) when (ex.SqlState == PostgresErrorCodes.InvalidCatalogName || ex.SqlState == PostgresErrorCodes.UndefinedTable) // DB doesn't exists
|
||||
{
|
||||
await postgresContext.Database.MigrateAsync();
|
||||
state = "pending";
|
||||
await SetMigrationState(postgresContext, migratingFrom, "pending");
|
||||
}
|
||||
|
||||
Logger.LogInformation($"Migrating from {migratingFrom} to Postgres...");
|
||||
if (state == "pending")
|
||||
{
|
||||
Logger.LogInformation($"There is a unfinished migration in postgres... dropping all tables");
|
||||
foreach (var t in postgresContext.Model.GetRelationalModel().Tables.OrderByTopology())
|
||||
{
|
||||
await postgresContext.Database.ExecuteSqlRawAsync($"DROP TABLE IF EXISTS \"{t.Name}\" CASCADE");
|
||||
}
|
||||
await postgresContext.Database.ExecuteSqlRawAsync($"DROP TABLE IF EXISTS \"__EFMigrationsHistory\" CASCADE");
|
||||
await postgresContext.Database.MigrateAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ConfigException("This database isn't created during a migration. Please use an empty database for postgres when migrating.");
|
||||
}
|
||||
await otherContext.Database.MigrateAsync();
|
||||
|
||||
await SetMigrationState(postgresContext, migratingFrom, "pending");
|
||||
|
||||
foreach (var t in postgresContext.Model.GetRelationalModel().Tables.OrderByTopology())
|
||||
{
|
||||
var typeMapping = t.EntityTypeMappings.Single();
|
||||
var query = (IQueryable<object>)otherContext.GetType().GetMethod("Set", new Type[0])!.MakeGenericMethod(typeMapping.TypeBase.ClrType).Invoke(otherContext, null)!;
|
||||
if (t.Name == "WebhookDeliveries" ||
|
||||
t.Name == "InvoiceWebhookDeliveries" ||
|
||||
t.Name == "StoreRoles")
|
||||
continue;
|
||||
Logger.LogInformation($"Migrating table: " + t.Name);
|
||||
List<PropertyInfo> datetimeProperties = new List<PropertyInfo>();
|
||||
foreach (var col in t.Columns)
|
||||
if (col.PropertyMappings.Single().Property.ClrType == typeof(DateTime))
|
||||
{
|
||||
datetimeProperties.Add(col.PropertyMappings.Single().Property.PropertyInfo!);
|
||||
}
|
||||
List<PropertyInfo> datetimeoffsetProperties = new List<PropertyInfo>();
|
||||
foreach (var col in t.Columns)
|
||||
if (col.PropertyMappings.Single().Property.ClrType == typeof(DateTimeOffset))
|
||||
{
|
||||
datetimeoffsetProperties.Add(col.PropertyMappings.Single().Property.PropertyInfo!);
|
||||
}
|
||||
var rows = await query.ToListAsync();
|
||||
foreach (var row in rows)
|
||||
{
|
||||
foreach (var prop in datetimeProperties)
|
||||
{
|
||||
var v = (DateTime)prop.GetValue(row)!;
|
||||
if (v.Kind == DateTimeKind.Unspecified)
|
||||
{
|
||||
v = new DateTime(v.Ticks, DateTimeKind.Utc);
|
||||
prop.SetValue(row, v);
|
||||
}
|
||||
else if (v.Kind == DateTimeKind.Local)
|
||||
{
|
||||
prop.SetValue(row, v.ToUniversalTime());
|
||||
}
|
||||
}
|
||||
foreach (var prop in datetimeoffsetProperties)
|
||||
{
|
||||
var v = (DateTimeOffset)prop.GetValue(row)!;
|
||||
if (v.Offset != TimeSpan.Zero)
|
||||
{
|
||||
prop.SetValue(row, v.ToOffset(TimeSpan.Zero));
|
||||
}
|
||||
}
|
||||
postgresContext.Entry(row).State = EntityState.Added;
|
||||
}
|
||||
await postgresContext.SaveChangesAsync();
|
||||
postgresContext.ChangeTracker.Clear();
|
||||
}
|
||||
await postgresContext.SaveChangesAsync();
|
||||
postgresContext.ChangeTracker.Clear();
|
||||
await UpdateSequenceInvoiceSearch(postgresContext);
|
||||
await SetMigrationState(postgresContext, migratingFrom, "complete");
|
||||
}
|
||||
otherContext.Dispose();
|
||||
SqliteConnection.ClearAllPools();
|
||||
MySqlConnection.ClearAllPools();
|
||||
|
||||
Logger.LogInformation($"Migration to postgres from {migratingFrom} successful");
|
||||
}
|
||||
|
||||
internal static async Task UpdateSequenceInvoiceSearch(ApplicationDbContext postgresContext)
|
||||
{
|
||||
await postgresContext.Database.ExecuteSqlRawAsync("SELECT SETVAL('\"InvoiceSearches_Id_seq\"', (SELECT max(\"Id\") FROM \"InvoiceSearches\"));");
|
||||
}
|
||||
|
||||
internal static async Task<string?> GetMigrationState(ApplicationDbContext postgresContext)
|
||||
{
|
||||
var o = (await postgresContext.Settings.FromSqlRaw("SELECT \"Id\", \"Value\" FROM \"Settings\" WHERE \"Id\"='MigrationData'").AsNoTracking().FirstOrDefaultAsync())?.Value;
|
||||
if (o is null)
|
||||
return null;
|
||||
return JObject.Parse(o)["state"]?.Value<string>();
|
||||
}
|
||||
private static async Task SetMigrationState(ApplicationDbContext postgresContext, string migratingFrom, string state)
|
||||
{
|
||||
await postgresContext.Database.ExecuteSqlRawAsync(
|
||||
"INSERT INTO \"Settings\" VALUES ('MigrationData', @p0::JSONB) ON CONFLICT (\"Id\") DO UPDATE SET \"Value\"=@p0::JSONB",
|
||||
new[] { $"{{ \"from\": \"{migratingFrom}\", \"state\": \"{state}\" }}" });
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,8 +33,6 @@ namespace BTCPayServer.Models.StoreViewModels
|
|||
public IFormFile CssFile { get; set; }
|
||||
public string CssFileId { get; set; }
|
||||
|
||||
public bool CanDelete { get; set; }
|
||||
|
||||
public bool Archived { get; set; }
|
||||
|
||||
[Display(Name = "Allow anyone to create invoice")]
|
||||
|
|
|
@ -335,8 +335,6 @@ namespace BTCPayServer.Services.Stores
|
|||
public async Task CleanUnreachableStores()
|
||||
{
|
||||
await using var ctx = _ContextFactory.CreateContext();
|
||||
if (!ctx.Database.SupportDropForeignKey())
|
||||
return;
|
||||
var events = new List<Events.StoreRemovedEvent>();
|
||||
foreach (var store in await ctx.Stores.Include(data => data.UserStores)
|
||||
.ThenInclude(store => store.StoreRole).Where(s =>
|
||||
|
@ -368,17 +366,14 @@ namespace BTCPayServer.Services.Stores
|
|||
private async Task DeleteStoreIfOrphan(string storeId)
|
||||
{
|
||||
await using var ctx = _ContextFactory.CreateContext();
|
||||
if (ctx.Database.SupportDropForeignKey())
|
||||
if (!await ctx.UserStore.Where(u => u.StoreDataId == storeId && u.StoreRole.Permissions.Contains(Policies.CanModifyStoreSettings)).AnyAsync())
|
||||
{
|
||||
if (!await ctx.UserStore.Where(u => u.StoreDataId == storeId && u.StoreRole.Permissions.Contains(Policies.CanModifyStoreSettings)).AnyAsync())
|
||||
var store = await ctx.Stores.FindAsync(storeId);
|
||||
if (store != null)
|
||||
{
|
||||
var store = await ctx.Stores.FindAsync(storeId);
|
||||
if (store != null)
|
||||
{
|
||||
ctx.Stores.Remove(store);
|
||||
await ctx.SaveChangesAsync();
|
||||
_eventAggregator.Publish(new StoreRemovedEvent(store.Id));
|
||||
}
|
||||
ctx.Stores.Remove(store);
|
||||
await ctx.SaveChangesAsync();
|
||||
_eventAggregator.Publish(new StoreRemovedEvent(store.Id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -559,8 +554,6 @@ namespace BTCPayServer.Services.Stores
|
|||
{
|
||||
int retry = 0;
|
||||
using var ctx = _ContextFactory.CreateContext();
|
||||
if (!ctx.Database.SupportDropForeignKey())
|
||||
return false;
|
||||
var store = await ctx.Stores.FindAsync(storeId);
|
||||
if (store == null)
|
||||
return false;
|
||||
|
@ -641,12 +634,6 @@ retry:
|
|||
{
|
||||
return ex.InnerException is Npgsql.PostgresException postgres && postgres.SqlState == "40P01";
|
||||
}
|
||||
|
||||
public bool CanDeleteStores()
|
||||
{
|
||||
using var ctx = _ContextFactory.CreateContext();
|
||||
return ctx.Database.SupportDropForeignKey();
|
||||
}
|
||||
}
|
||||
|
||||
public record StoreRoleId
|
||||
|
|
|
@ -55,7 +55,6 @@ namespace BTCPayServer.Services
|
|||
public string? Type { get; set; }
|
||||
public string[]? Ids { get; set; }
|
||||
public bool IncludeNeighbours { get; set; } = true;
|
||||
public bool UseInefficientPath { get; set; }
|
||||
|
||||
public static IEnumerable<ObjectTypeId> Get(ReceivedCoin coin)
|
||||
{
|
||||
|
@ -96,151 +95,118 @@ namespace BTCPayServer.Services
|
|||
// pg_stat_statements output, making it impossible to analyze the performance impact of this query.
|
||||
// On top of this, the entity version is doing 2 left join to satisfy the Include queries, resulting in n*m row returned for each transaction.
|
||||
// n being the number of children, m the number of parents.
|
||||
if (ctx.Database.IsNpgsql() && !queryObject.UseInefficientPath)
|
||||
var connection = ctx.Database.GetDbConnection();
|
||||
if (connection.State != System.Data.ConnectionState.Open)
|
||||
await connection.OpenAsync();
|
||||
|
||||
string walletIdFilter = queryObject.WalletId is not null ? " AND wos.\"WalletId\"=@walletId" : "";
|
||||
string typeFilter = queryObject.Type is not null ? " AND wos.\"Type\"=@type" : "";
|
||||
var cmd = connection.CreateCommand();
|
||||
var selectWalletObjects =
|
||||
queryObject.TypesIds is not null ?
|
||||
$"SELECT wos.* FROM unnest(@ids, @types) t(i,t) JOIN \"WalletObjects\" wos ON true{walletIdFilter} AND wos.\"Type\"=t AND wos.\"Id\"=i" :
|
||||
queryObject.Ids is null ?
|
||||
$"SELECT wos.* FROM \"WalletObjects\" wos WHERE true{walletIdFilter}{typeFilter} " :
|
||||
queryObject.Ids.Length == 1 ?
|
||||
$"SELECT wos.* FROM \"WalletObjects\" wos WHERE true{walletIdFilter} AND wos.\"Type\"=@type AND wos.\"Id\"=@id" :
|
||||
$"SELECT wos.* FROM unnest(@ids) t JOIN \"WalletObjects\" wos ON true{walletIdFilter} AND wos.\"Type\"=@type AND wos.\"Id\"=t";
|
||||
|
||||
var includeNeighbourSelect = queryObject.IncludeNeighbours ? ", wos2.\"Data\" AS \"Data2\"" : "";
|
||||
var includeNeighbourJoin = queryObject.IncludeNeighbours ? "LEFT JOIN \"WalletObjects\" wos2 ON wos.\"WalletId\"=wos2.\"WalletId\" AND wol.\"Type2\"=wos2.\"Type\" AND wol.\"Id2\"=wos2.\"Id\"" : "";
|
||||
var query =
|
||||
$"SELECT wos.\"WalletId\", wos.\"Id\", wos.\"Type\", wos.\"Data\", wol.\"LinkData\", wol.\"Type2\", wol.\"Id2\"{includeNeighbourSelect} FROM ({selectWalletObjects}) wos " +
|
||||
$"LEFT JOIN LATERAL ( " +
|
||||
"SELECT \"AType\" AS \"Type2\", \"AId\" AS \"Id2\", \"Data\" AS \"LinkData\" FROM \"WalletObjectLinks\" WHERE \"WalletId\"=wos.\"WalletId\" AND \"BType\"=wos.\"Type\" AND \"BId\"=wos.\"Id\" " +
|
||||
"UNION " +
|
||||
"SELECT \"BType\" AS \"Type2\", \"BId\" AS \"Id2\", \"Data\" AS \"LinkData\" FROM \"WalletObjectLinks\" WHERE \"WalletId\"=wos.\"WalletId\" AND \"AType\"=wos.\"Type\" AND \"AId\"=wos.\"Id\"" +
|
||||
$" ) wol ON true " + includeNeighbourJoin;
|
||||
cmd.CommandText = query;
|
||||
if (queryObject.WalletId is not null)
|
||||
{
|
||||
var connection = ctx.Database.GetDbConnection();
|
||||
if (connection.State != System.Data.ConnectionState.Open)
|
||||
await connection.OpenAsync();
|
||||
|
||||
string walletIdFilter = queryObject.WalletId is not null ? " AND wos.\"WalletId\"=@walletId" : "";
|
||||
string typeFilter = queryObject.Type is not null ? " AND wos.\"Type\"=@type" : "";
|
||||
var cmd = connection.CreateCommand();
|
||||
var selectWalletObjects =
|
||||
queryObject.TypesIds is not null ?
|
||||
$"SELECT wos.* FROM unnest(@ids, @types) t(i,t) JOIN \"WalletObjects\" wos ON true{walletIdFilter} AND wos.\"Type\"=t AND wos.\"Id\"=i" :
|
||||
queryObject.Ids is null ?
|
||||
$"SELECT wos.* FROM \"WalletObjects\" wos WHERE true{walletIdFilter}{typeFilter} " :
|
||||
queryObject.Ids.Length == 1 ?
|
||||
$"SELECT wos.* FROM \"WalletObjects\" wos WHERE true{walletIdFilter} AND wos.\"Type\"=@type AND wos.\"Id\"=@id" :
|
||||
$"SELECT wos.* FROM unnest(@ids) t JOIN \"WalletObjects\" wos ON true{walletIdFilter} AND wos.\"Type\"=@type AND wos.\"Id\"=t";
|
||||
|
||||
var includeNeighbourSelect = queryObject.IncludeNeighbours ? ", wos2.\"Data\" AS \"Data2\"" : "";
|
||||
var includeNeighbourJoin = queryObject.IncludeNeighbours ? "LEFT JOIN \"WalletObjects\" wos2 ON wos.\"WalletId\"=wos2.\"WalletId\" AND wol.\"Type2\"=wos2.\"Type\" AND wol.\"Id2\"=wos2.\"Id\"" : "";
|
||||
var query =
|
||||
$"SELECT wos.\"WalletId\", wos.\"Id\", wos.\"Type\", wos.\"Data\", wol.\"LinkData\", wol.\"Type2\", wol.\"Id2\"{includeNeighbourSelect} FROM ({selectWalletObjects}) wos " +
|
||||
$"LEFT JOIN LATERAL ( " +
|
||||
"SELECT \"AType\" AS \"Type2\", \"AId\" AS \"Id2\", \"Data\" AS \"LinkData\" FROM \"WalletObjectLinks\" WHERE \"WalletId\"=wos.\"WalletId\" AND \"BType\"=wos.\"Type\" AND \"BId\"=wos.\"Id\" " +
|
||||
"UNION " +
|
||||
"SELECT \"BType\" AS \"Type2\", \"BId\" AS \"Id2\", \"Data\" AS \"LinkData\" FROM \"WalletObjectLinks\" WHERE \"WalletId\"=wos.\"WalletId\" AND \"AType\"=wos.\"Type\" AND \"AId\"=wos.\"Id\"" +
|
||||
$" ) wol ON true " + includeNeighbourJoin;
|
||||
cmd.CommandText = query;
|
||||
if (queryObject.WalletId is not null)
|
||||
{
|
||||
var walletIdParam = cmd.CreateParameter();
|
||||
walletIdParam.ParameterName = "walletId";
|
||||
walletIdParam.Value = queryObject.WalletId.ToString();
|
||||
walletIdParam.DbType = System.Data.DbType.String;
|
||||
cmd.Parameters.Add(walletIdParam);
|
||||
}
|
||||
|
||||
if (queryObject.Type != null)
|
||||
{
|
||||
var typeParam = cmd.CreateParameter();
|
||||
typeParam.ParameterName = "type";
|
||||
typeParam.Value = queryObject.Type;
|
||||
typeParam.DbType = System.Data.DbType.String;
|
||||
cmd.Parameters.Add(typeParam);
|
||||
}
|
||||
|
||||
if (queryObject.TypesIds != null)
|
||||
{
|
||||
var typesParam = cmd.CreateParameter();
|
||||
typesParam.ParameterName = "types";
|
||||
typesParam.Value = queryObject.TypesIds.Select(t => t.Type).ToList();
|
||||
typesParam.DbType = System.Data.DbType.Object;
|
||||
cmd.Parameters.Add(typesParam);
|
||||
var idParam = cmd.CreateParameter();
|
||||
idParam.ParameterName = "ids";
|
||||
idParam.Value = queryObject.TypesIds.Select(t => t.Id).ToList();
|
||||
idParam.DbType = System.Data.DbType.Object;
|
||||
cmd.Parameters.Add(idParam);
|
||||
}
|
||||
|
||||
if (queryObject.Ids != null)
|
||||
{
|
||||
if (queryObject.Ids.Length == 1)
|
||||
{
|
||||
var txIdParam = cmd.CreateParameter();
|
||||
txIdParam.ParameterName = "id";
|
||||
txIdParam.Value = queryObject.Ids[0];
|
||||
txIdParam.DbType = System.Data.DbType.String;
|
||||
cmd.Parameters.Add(txIdParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
var txIdsParam = cmd.CreateParameter();
|
||||
txIdsParam.ParameterName = "ids";
|
||||
txIdsParam.Value = queryObject.Ids.ToList();
|
||||
txIdsParam.DbType = System.Data.DbType.Object;
|
||||
cmd.Parameters.Add(txIdsParam);
|
||||
}
|
||||
}
|
||||
await using var reader = await cmd.ExecuteReaderAsync();
|
||||
var wosById = new Dictionary<WalletObjectId, WalletObjectData>();
|
||||
while (await reader.ReadAsync())
|
||||
{
|
||||
WalletObjectData wo = new WalletObjectData();
|
||||
wo.WalletId = (string)reader["WalletId"];
|
||||
wo.Type = (string)reader["Type"];
|
||||
wo.Id = (string)reader["Id"];
|
||||
var id = new WalletObjectId(WalletId.Parse(wo.WalletId), wo.Type, wo.Id);
|
||||
wo.Data = reader["Data"] is DBNull ? null : (string)reader["Data"];
|
||||
if (wosById.TryGetValue(id, out var wo2))
|
||||
wo = wo2;
|
||||
else
|
||||
{
|
||||
wosById.Add(id, wo);
|
||||
wo.Bs = new List<WalletObjectLinkData>();
|
||||
}
|
||||
if (reader["Type2"] is not DBNull)
|
||||
{
|
||||
var l = new WalletObjectLinkData()
|
||||
{
|
||||
BType = (string)reader["Type2"],
|
||||
BId = (string)reader["Id2"],
|
||||
Data = reader["LinkData"] is DBNull ? null : (string)reader["LinkData"]
|
||||
};
|
||||
wo.Bs.Add(l);
|
||||
l.B = new WalletObjectData()
|
||||
{
|
||||
Type = l.BType,
|
||||
Id = l.BId,
|
||||
Data = (!queryObject.IncludeNeighbours || reader["Data2"] is DBNull) ? null : (string)reader["Data2"]
|
||||
};
|
||||
}
|
||||
}
|
||||
return wosById;
|
||||
var walletIdParam = cmd.CreateParameter();
|
||||
walletIdParam.ParameterName = "walletId";
|
||||
walletIdParam.Value = queryObject.WalletId.ToString();
|
||||
walletIdParam.DbType = System.Data.DbType.String;
|
||||
cmd.Parameters.Add(walletIdParam);
|
||||
}
|
||||
else // Unefficient path
|
||||
|
||||
if (queryObject.Type != null)
|
||||
{
|
||||
IQueryable<WalletObjectData> q;
|
||||
if (queryObject.TypesIds is not null)
|
||||
var typeParam = cmd.CreateParameter();
|
||||
typeParam.ParameterName = "type";
|
||||
typeParam.Value = queryObject.Type;
|
||||
typeParam.DbType = System.Data.DbType.String;
|
||||
cmd.Parameters.Add(typeParam);
|
||||
}
|
||||
|
||||
if (queryObject.TypesIds != null)
|
||||
{
|
||||
var typesParam = cmd.CreateParameter();
|
||||
typesParam.ParameterName = "types";
|
||||
typesParam.Value = queryObject.TypesIds.Select(t => t.Type).ToList();
|
||||
typesParam.DbType = System.Data.DbType.Object;
|
||||
cmd.Parameters.Add(typesParam);
|
||||
var idParam = cmd.CreateParameter();
|
||||
idParam.ParameterName = "ids";
|
||||
idParam.Value = queryObject.TypesIds.Select(t => t.Id).ToList();
|
||||
idParam.DbType = System.Data.DbType.Object;
|
||||
cmd.Parameters.Add(idParam);
|
||||
}
|
||||
|
||||
if (queryObject.Ids != null)
|
||||
{
|
||||
if (queryObject.Ids.Length == 1)
|
||||
{
|
||||
// Note this is problematic if the type contains '##', but I don't see how to do it properly with entity framework
|
||||
var idTypes = queryObject.TypesIds.Select(o => $"{o.Type}##{o.Id}").ToArray();
|
||||
q = ctx.WalletObjects
|
||||
.Where(w => (queryObject.WalletId == null || w.WalletId == queryObject.WalletId.ToString()) && idTypes.Contains(w.Type + "##" + w.Id));
|
||||
var txIdParam = cmd.CreateParameter();
|
||||
txIdParam.ParameterName = "id";
|
||||
txIdParam.Value = queryObject.Ids[0];
|
||||
txIdParam.DbType = System.Data.DbType.String;
|
||||
cmd.Parameters.Add(txIdParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
q = ctx.WalletObjects
|
||||
.Where(w => (queryObject.WalletId == null || w.WalletId == queryObject.WalletId.ToString()) && (queryObject.Type == null || w.Type == queryObject.Type) && (queryObject.Ids == null || queryObject.Ids.Contains(w.Id)));
|
||||
var txIdsParam = cmd.CreateParameter();
|
||||
txIdsParam.ParameterName = "ids";
|
||||
txIdsParam.Value = queryObject.Ids.ToList();
|
||||
txIdsParam.DbType = System.Data.DbType.Object;
|
||||
cmd.Parameters.Add(txIdsParam);
|
||||
}
|
||||
if (queryObject.IncludeNeighbours)
|
||||
{
|
||||
q = q.Include(o => o.Bs).ThenInclude(o => o.B)
|
||||
.Include(o => o.As).ThenInclude(o => o.A);
|
||||
}
|
||||
q = q.AsNoTracking();
|
||||
|
||||
var wosById = new Dictionary<WalletObjectId, WalletObjectData>();
|
||||
foreach (var row in await q.ToListAsync())
|
||||
{
|
||||
var id = new WalletObjectId(WalletId.Parse(row.WalletId), row.Type, row.Id);
|
||||
wosById.TryAdd(id, row);
|
||||
}
|
||||
return wosById;
|
||||
}
|
||||
await using var reader = await cmd.ExecuteReaderAsync();
|
||||
var wosById = new Dictionary<WalletObjectId, WalletObjectData>();
|
||||
while (await reader.ReadAsync())
|
||||
{
|
||||
WalletObjectData wo = new WalletObjectData();
|
||||
wo.WalletId = (string)reader["WalletId"];
|
||||
wo.Type = (string)reader["Type"];
|
||||
wo.Id = (string)reader["Id"];
|
||||
var id = new WalletObjectId(WalletId.Parse(wo.WalletId), wo.Type, wo.Id);
|
||||
wo.Data = reader["Data"] is DBNull ? null : (string)reader["Data"];
|
||||
if (wosById.TryGetValue(id, out var wo2))
|
||||
wo = wo2;
|
||||
else
|
||||
{
|
||||
wosById.Add(id, wo);
|
||||
wo.Bs = new List<WalletObjectLinkData>();
|
||||
}
|
||||
if (reader["Type2"] is not DBNull)
|
||||
{
|
||||
var l = new WalletObjectLinkData()
|
||||
{
|
||||
BType = (string)reader["Type2"],
|
||||
BId = (string)reader["Id2"],
|
||||
Data = reader["LinkData"] is DBNull ? null : (string)reader["LinkData"]
|
||||
};
|
||||
wo.Bs.Add(l);
|
||||
l.B = new WalletObjectData()
|
||||
{
|
||||
Type = l.BType,
|
||||
Id = l.BId,
|
||||
Data = (!queryObject.IncludeNeighbours || reader["Data2"] is DBNull) ? null : (string)reader["Data2"]
|
||||
};
|
||||
}
|
||||
}
|
||||
return wosById;
|
||||
}
|
||||
#nullable restore
|
||||
|
||||
|
|
|
@ -176,10 +176,7 @@
|
|||
}
|
||||
</button>
|
||||
</form>
|
||||
@if (Model.CanDelete)
|
||||
{
|
||||
<a id="DeleteStore" class="btn btn-outline-danger" asp-action="DeleteStore" asp-route-storeId="@Model.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The store <strong>@Html.Encode(Model.StoreName)</strong> will be permanently deleted. This action will also delete all invoices, apps and data associated with the store." data-confirm-input="DELETE">Delete this store</a>
|
||||
}
|
||||
<a id="DeleteStore" class="btn btn-outline-danger" asp-action="DeleteStore" asp-route-storeId="@Model.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The store <strong>@Html.Encode(Model.StoreName)</strong> will be permanently deleted. This action will also delete all invoices, apps and data associated with the store." data-confirm-input="DELETE">Delete this store</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Reference in a new issue