From ef9c2e8af1353b4da22168f5ad840d657bafdf57 Mon Sep 17 00:00:00 2001 From: Andrew Camilleri Date: Fri, 24 May 2019 06:17:02 +0000 Subject: [PATCH] Part2: Openiddict: Init OpenIddict & Database Migration & Auth Policies (#567) * Part 1: OpenIddict - Minor Changes & Config prep * Part 1: OpenIddict - Minor Changes & Config prep * Part2: Openiddict: Init OpenIddict & Database Migration & Auth Policies * pr changes * pr changes * fix merge * pr fixes * remove config for openid -- no need for it for now * fix compile * fix compile #2 * remove extra ns using * Update Startup.cs * compile * adjust settings a bit * remove duplicate * remove external login provider placeholder html * remove unused directives * regenerate db snapshot model * Remove dynamic policy --- BTCPayServer.Tests/BTCPayServerTester.cs | 3 +- .../Models/BTCPayOpenIdAuthorization.cs | 6 + .../OpenId/Models/BTCPayOpenIdClient.cs | 11 + .../OpenId/Models/BTCPayOpenIdToken.cs | 6 + BTCPayServer/Data/ApplicationDbContext.cs | 5 + .../Extensions/OpenIddictExtensions.cs | 37 + BTCPayServer/Extensions/RsaKeyExtensions.cs | 97 +++ BTCPayServer/Hosting/BTCPayServerServices.cs | 23 +- BTCPayServer/Hosting/Startup.cs | 89 +- .../20190225091644_AddOpenIddict.Designer.cs | 787 ++++++++++++++++++ .../20190225091644_AddOpenIddict.cs | 167 ++++ .../ApplicationDbContextModelSnapshot.cs | 179 ++++ BTCPayServer/Models/ApplicationUser.cs | 3 + BTCPayServer/Security/Policies.cs | 3 +- BTCPayServer/Views/Account/Login.cshtml | 35 +- 15 files changed, 1381 insertions(+), 70 deletions(-) create mode 100644 BTCPayServer/Authentication/OpenId/Models/BTCPayOpenIdAuthorization.cs create mode 100644 BTCPayServer/Authentication/OpenId/Models/BTCPayOpenIdClient.cs create mode 100644 BTCPayServer/Authentication/OpenId/Models/BTCPayOpenIdToken.cs create mode 100644 BTCPayServer/Extensions/OpenIddictExtensions.cs create mode 100644 BTCPayServer/Extensions/RsaKeyExtensions.cs create mode 100644 BTCPayServer/Migrations/20190225091644_AddOpenIddict.Designer.cs create mode 100644 BTCPayServer/Migrations/20190225091644_AddOpenIddict.cs diff --git a/BTCPayServer.Tests/BTCPayServerTester.cs b/BTCPayServer.Tests/BTCPayServerTester.cs index 7d09d69c6..ca56a0249 100644 --- a/BTCPayServer.Tests/BTCPayServerTester.cs +++ b/BTCPayServer.Tests/BTCPayServerTester.cs @@ -33,6 +33,7 @@ using System.Security.Claims; using System.Security.Principal; using System.Text; using System.Threading; +using AspNet.Security.OpenIdConnect.Primitives; using Xunit; using BTCPayServer.Services; using System.Net.Http; @@ -283,7 +284,7 @@ namespace BTCPayServer.Tests if (userId != null) { List claims = new List(); - claims.Add(new Claim(ClaimTypes.NameIdentifier, userId)); + claims.Add(new Claim(OpenIdConnectConstants.Claims.Subject, userId)); if (additionalClaims != null) claims.AddRange(additionalClaims); context.User = new ClaimsPrincipal(new ClaimsIdentity(claims.ToArray(), Policies.CookieAuthentication)); diff --git a/BTCPayServer/Authentication/OpenId/Models/BTCPayOpenIdAuthorization.cs b/BTCPayServer/Authentication/OpenId/Models/BTCPayOpenIdAuthorization.cs new file mode 100644 index 000000000..09dbf3691 --- /dev/null +++ b/BTCPayServer/Authentication/OpenId/Models/BTCPayOpenIdAuthorization.cs @@ -0,0 +1,6 @@ +using OpenIddict.EntityFrameworkCore.Models; + +namespace BTCPayServer.Authentication.OpenId.Models +{ + public class BTCPayOpenIdAuthorization : OpenIddictAuthorization { } +} \ No newline at end of file diff --git a/BTCPayServer/Authentication/OpenId/Models/BTCPayOpenIdClient.cs b/BTCPayServer/Authentication/OpenId/Models/BTCPayOpenIdClient.cs new file mode 100644 index 000000000..bf2abb797 --- /dev/null +++ b/BTCPayServer/Authentication/OpenId/Models/BTCPayOpenIdClient.cs @@ -0,0 +1,11 @@ +using BTCPayServer.Models; +using OpenIddict.EntityFrameworkCore.Models; + +namespace BTCPayServer.Authentication.OpenId.Models +{ + public class BTCPayOpenIdClient: OpenIddictApplication + { + public string ApplicationUserId { get; set; } + public ApplicationUser ApplicationUser { get; set; } + } +} diff --git a/BTCPayServer/Authentication/OpenId/Models/BTCPayOpenIdToken.cs b/BTCPayServer/Authentication/OpenId/Models/BTCPayOpenIdToken.cs new file mode 100644 index 000000000..00714240a --- /dev/null +++ b/BTCPayServer/Authentication/OpenId/Models/BTCPayOpenIdToken.cs @@ -0,0 +1,6 @@ +using OpenIddict.EntityFrameworkCore.Models; + +namespace BTCPayServer.Authentication.OpenId.Models +{ + public class BTCPayOpenIdToken : OpenIddictToken { } +} \ No newline at end of file diff --git a/BTCPayServer/Data/ApplicationDbContext.cs b/BTCPayServer/Data/ApplicationDbContext.cs index 473de8f8d..964dd1a9d 100644 --- a/BTCPayServer/Data/ApplicationDbContext.cs +++ b/BTCPayServer/Data/ApplicationDbContext.cs @@ -1,4 +1,5 @@ using System.Linq; +using BTCPayServer.Authentication.OpenId.Models; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using BTCPayServer.Models; @@ -6,6 +7,7 @@ using BTCPayServer.Services.PaymentRequests; using BTCPayServer.Services.U2F.Models; using BTCPayServer.Storage.Models; using Microsoft.EntityFrameworkCore.Infrastructure; +using OpenIddict.EntityFrameworkCore.Models; namespace BTCPayServer.Data { @@ -225,6 +227,9 @@ namespace BTCPayServer.Data builder.Entity() .HasIndex(o => o.Status); + + builder.UseOpenIddict, BTCPayOpenIdToken, string>(); + } } diff --git a/BTCPayServer/Extensions/OpenIddictExtensions.cs b/BTCPayServer/Extensions/OpenIddictExtensions.cs new file mode 100644 index 000000000..befccf6fa --- /dev/null +++ b/BTCPayServer/Extensions/OpenIddictExtensions.cs @@ -0,0 +1,37 @@ +using System.IO; +using System.Security.Cryptography; +using BTCPayServer.Configuration; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Tokens; +using NETCore.Encrypt.Extensions.Internal; + +namespace BTCPayServer +{ + public static class OpenIddictExtensions + { + public static OpenIddictServerBuilder ConfigureSigningKey(this OpenIddictServerBuilder builder, + IConfiguration configuration) + { + + var file = Path.Combine(configuration.GetDataDir(), "rsaparams"); + + RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(2048); + RsaSecurityKey key = null; + + if (File.Exists(file)) + { + RSA.FromXmlString2( File.ReadAllText(file)); + } + else + { + var contents = RSA.ToXmlString2(true); + File.WriteAllText(file,contents ); + } + + RSAParameters KeyParam = RSA.ExportParameters(true); + key = new RsaSecurityKey(KeyParam); + return builder.AddSigningKey(key); + } + } +} diff --git a/BTCPayServer/Extensions/RsaKeyExtensions.cs b/BTCPayServer/Extensions/RsaKeyExtensions.cs new file mode 100644 index 000000000..c201917bb --- /dev/null +++ b/BTCPayServer/Extensions/RsaKeyExtensions.cs @@ -0,0 +1,97 @@ +using System; +using System.Globalization; +using System.Security.Cryptography; +using System.Xml; + +namespace NETCore.Encrypt.Extensions.Internal +{ + /// + /// .net core's implementatiosn are still marked as unsupported because of stupid decisions( https://github.com/dotnet/corefx/issues/23686) + /// + internal static class RsaKeyExtensions + { + #region XML + + public static void FromXmlString2(this RSA rsa, string xmlString) + { + RSAParameters parameters = new RSAParameters(); + + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.LoadXml(xmlString); + + if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue", StringComparison.InvariantCulture)) + { + foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes) + { + switch (node.Name) + { + case "Modulus": + parameters.Modulus = (string.IsNullOrEmpty(node.InnerText) + ? null + : Convert.FromBase64String(node.InnerText)); + break; + case "Exponent": + parameters.Exponent = (string.IsNullOrEmpty(node.InnerText) + ? null + : Convert.FromBase64String(node.InnerText)); + break; + case "P": + parameters.P = (string.IsNullOrEmpty(node.InnerText) + ? null + : Convert.FromBase64String(node.InnerText)); + break; + case "Q": + parameters.Q = (string.IsNullOrEmpty(node.InnerText) + ? null + : Convert.FromBase64String(node.InnerText)); + break; + case "DP": + parameters.DP = (string.IsNullOrEmpty(node.InnerText) + ? null + : Convert.FromBase64String(node.InnerText)); + break; + case "DQ": + parameters.DQ = (string.IsNullOrEmpty(node.InnerText) + ? null + : Convert.FromBase64String(node.InnerText)); + break; + case "InverseQ": + parameters.InverseQ = (string.IsNullOrEmpty(node.InnerText) + ? null + : Convert.FromBase64String(node.InnerText)); + break; + case "D": + parameters.D = (string.IsNullOrEmpty(node.InnerText) + ? null + : Convert.FromBase64String(node.InnerText)); + break; + } + } + } + else + { + throw new Exception("Invalid XML RSA key."); + } + + rsa.ImportParameters(parameters); + } + + public static string ToXmlString2(this RSA rsa, bool includePrivateParameters) + { + RSAParameters parameters = rsa.ExportParameters(includePrivateParameters); + + return string.Format(CultureInfo.InvariantCulture, + "{0}{1}

{2}

{3}{4}{5}{6}{7}
", + parameters.Modulus != null ? Convert.ToBase64String(parameters.Modulus) : null, + parameters.Exponent != null ? Convert.ToBase64String(parameters.Exponent) : null, + parameters.P != null ? Convert.ToBase64String(parameters.P) : null, + parameters.Q != null ? Convert.ToBase64String(parameters.Q) : null, + parameters.DP != null ? Convert.ToBase64String(parameters.DP) : null, + parameters.DQ != null ? Convert.ToBase64String(parameters.DQ) : null, + parameters.InverseQ != null ? Convert.ToBase64String(parameters.InverseQ) : null, + parameters.D != null ? Convert.ToBase64String(parameters.D) : null); + } + + #endregion + } +} diff --git a/BTCPayServer/Hosting/BTCPayServerServices.cs b/BTCPayServer/Hosting/BTCPayServerServices.cs index c935263b4..fe25aba4a 100644 --- a/BTCPayServer/Hosting/BTCPayServerServices.cs +++ b/BTCPayServer/Hosting/BTCPayServerServices.cs @@ -1,9 +1,7 @@ using BTCPayServer.Configuration; using Microsoft.Extensions.Logging; -using Microsoft.AspNetCore.Hosting; using System; -using System.Collections.Generic; -using System.Text; +using System.IdentityModel.Tokens.Jwt; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.AspNetCore.Http; @@ -12,7 +10,6 @@ using NBitcoin; using BTCPayServer.Data; using Microsoft.EntityFrameworkCore; using System.IO; -using NBXplorer; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Hosting; using BTCPayServer.Services; @@ -21,19 +18,15 @@ using BTCPayServer.Services.Rates; using BTCPayServer.Services.Stores; using BTCPayServer.Services.Fees; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Rewrite; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; -using Microsoft.AspNetCore.Authorization; using BTCPayServer.Controllers; using BTCPayServer.Services.Mails; using Microsoft.AspNetCore.Identity; -using BTCPayServer.Models; -using System.Threading.Tasks; using System.Threading; using BTCPayServer.Services.Wallets; using BTCPayServer.Authentication; -using Microsoft.Extensions.Caching.Memory; +using BTCPayServer.Authentication.OpenId.Models; using BTCPayServer.Logging; using BTCPayServer.HostedServices; using System.Security.Claims; @@ -44,11 +37,13 @@ using BTCPayServer.Payments.Changelly; using BTCPayServer.Payments.Lightning; using BTCPayServer.Security; using BTCPayServer.Services.PaymentRequests; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Mvc.ModelBinding; using NBXplorer.DerivationStrategy; using NicolasDorier.RateLimits; using Npgsql; using BTCPayServer.Services.Apps; +using OpenIddict.EntityFrameworkCore.Models; using BTCPayServer.Services.U2F; using BundlerMinifier.TagHelpers; @@ -62,6 +57,7 @@ namespace BTCPayServer.Hosting { var factory = provider.GetRequiredService(); factory.ConfigureBuilder(o); + o.UseOpenIddict, BTCPayOpenIdToken, string>(); }); services.AddHttpClient(); services.TryAddSingleton(); @@ -250,7 +246,16 @@ namespace BTCPayServer.Hosting private static void AddBtcPayServerAuthenticationSchemes(this IServiceCollection services, IConfiguration configuration) { + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); + JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear(); + services.AddAuthentication() + .AddJwtBearer(options => + { +// options.RequireHttpsMetadata = false; +// options.TokenValidationParameters.ValidateAudience = false; + options.TokenValidationParameters.ValidateIssuer = false; + }) .AddCookie() .AddBitpayAuthentication(); } diff --git a/BTCPayServer/Hosting/Startup.cs b/BTCPayServer/Hosting/Startup.cs index 6a1393d14..d0662234f 100644 --- a/BTCPayServer/Hosting/Startup.cs +++ b/BTCPayServer/Hosting/Startup.cs @@ -1,45 +1,28 @@ using Microsoft.AspNetCore.Hosting; -using System.Reflection; -using System.Linq; using Microsoft.AspNetCore.Builder; using System; -using System.Text; using Microsoft.Extensions.DependencyInjection; - -using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; -using Microsoft.AspNetCore.Mvc; -using NBitpayClient; -using BTCPayServer.Authentication; -using Microsoft.EntityFrameworkCore; using BTCPayServer.Filters; -using Microsoft.AspNetCore.Mvc.Infrastructure; using BTCPayServer.Models; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.HttpOverrides; using BTCPayServer.Data; using Microsoft.Extensions.Logging; using BTCPayServer.Logging; -using Microsoft.AspNetCore.Authorization; -using System.Threading.Tasks; -using BTCPayServer.Controllers; -using BTCPayServer.Services.Stores; -using BTCPayServer.Services.Mails; using Microsoft.Extensions.Configuration; using BTCPayServer.Configuration; using System.IO; using Microsoft.Extensions.DependencyInjection.Extensions; -using System.Threading; -using Microsoft.Extensions.Options; -using Microsoft.AspNetCore.Mvc.Cors.Internal; +using AspNet.Security.OpenIdConnect.Primitives; +using BTCPayServer.Authentication.OpenId.Models; +using BTCPayServer.Security; using Microsoft.AspNetCore.Server.Kestrel.Core; +using OpenIddict.Abstractions; +using OpenIddict.EntityFrameworkCore.Models; using System.Net; using BTCPayServer.PaymentRequest; -using BTCPayServer.Security; using BTCPayServer.Services.Apps; using BTCPayServer.Storage; -using BTCPayServer.Storage.Services.Providers.FileSystemStorage; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.FileProviders; namespace BTCPayServer.Hosting { @@ -65,11 +48,14 @@ namespace BTCPayServer.Hosting services.AddMemoryCache(); services.AddIdentity() .AddEntityFrameworkStores() - .AddDefaultTokenProviders(); - services.AddSignalR(); + .AddDefaultTokenProviders(); + + ConfigureOpenIddict(services); + + services.AddBTCPayServer(Configuration); services.AddProviderStorage(); services.AddSession(); - services.AddBTCPayServer(Configuration); + services.AddSignalR(); services.AddMvc(o => { o.Filters.Add(new XFrameOptionsAttribute("DENY")); @@ -96,6 +82,13 @@ namespace BTCPayServer.Hosting options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5); options.Lockout.MaxFailedAccessAttempts = 5; options.Lockout.AllowedForNewUsers = true; + options.Password.RequireUppercase = false; + // Configure Identity to use the same JWT claims as OpenIddict instead + // of the legacy WS-Federation claims it uses by default (ClaimTypes), + // which saves you from doing the mapping in your authorization controller. + options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name; + options.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject; + options.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role; }); // If the HTTPS certificate path is not set this logic will NOT be used and the default Kestrel binding logic will be. string httpsCertificateFilePath = Configuration.GetOrDefault("HttpsCertificateFilePath", null); @@ -135,6 +128,50 @@ namespace BTCPayServer.Hosting } } + private void ConfigureOpenIddict(IServiceCollection services) + { +// Register the OpenIddict services. + services.AddOpenIddict() + .AddCore(options => + { + // Configure OpenIddict to use the Entity Framework Core stores and entities. + options.UseEntityFrameworkCore() + .UseDbContext() + .ReplaceDefaultEntities, + BTCPayOpenIdToken, string>(); + }) + .AddServer(options => + { + // Register the ASP.NET Core MVC binder used by OpenIddict. + // Note: if you don't call this method, you won't be able to + // bind OpenIdConnectRequest or OpenIdConnectResponse parameters. + options.UseMvc(); + + // Enable the token endpoint (required to use the password flow). + options.EnableTokenEndpoint("/connect/token"); + options.EnableAuthorizationEndpoint("/connect/authorize"); + options.EnableAuthorizationEndpoint("/connect/logout"); + + // Allow client applications various flows + options.AllowImplicitFlow(); + options.AllowClientCredentialsFlow(); + options.AllowRefreshTokenFlow(); + options.AllowPasswordFlow(); + options.AllowAuthorizationCodeFlow(); + options.UseRollingTokens(); + options.UseJsonWebTokens(); + + options.RegisterScopes( + OpenIdConnectConstants.Scopes.OpenId, + OpenIdConnectConstants.Scopes.OfflineAccess, + OpenIdConnectConstants.Scopes.Email, + OpenIdConnectConstants.Scopes.Profile, + OpenIddictConstants.Scopes.Roles); + + options.ConfigureSigningKey(Configuration); + }); + } + public void Configure( IApplicationBuilder app, IHostingEnvironment env, @@ -162,6 +199,8 @@ namespace BTCPayServer.Hosting { app.UseDeveloperExceptionPage(); } + + app.UseCors(); var forwardingOptions = new ForwardedHeadersOptions() { diff --git a/BTCPayServer/Migrations/20190225091644_AddOpenIddict.Designer.cs b/BTCPayServer/Migrations/20190225091644_AddOpenIddict.Designer.cs new file mode 100644 index 000000000..abc0aa76c --- /dev/null +++ b/BTCPayServer/Migrations/20190225091644_AddOpenIddict.Designer.cs @@ -0,0 +1,787 @@ +// +using System; +using BTCPayServer.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace BTCPayServer.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20190225091644_AddOpenIddict")] + partial class AddOpenIddict + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.4-rtm-31024"); + + modelBuilder.Entity("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ApplicationId"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50); + + b.Property("Properties"); + + b.Property("Scopes"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(25); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(450); + + b.Property("Type") + .IsRequired() + .HasMaxLength(25); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations"); + }); + + modelBuilder.Entity("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdClient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ApplicationUserId"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(100); + + b.Property("ClientSecret"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50); + + b.Property("ConsentType"); + + b.Property("DisplayName"); + + b.Property("Permissions"); + + b.Property("PostLogoutRedirectUris"); + + b.Property("Properties"); + + b.Property("RedirectUris"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(25); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.HasIndex("ClientId") + .IsUnique(); + + b.ToTable("OpenIddictApplications"); + }); + + modelBuilder.Entity("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ApplicationId"); + + b.Property("AuthorizationId"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50); + + b.Property("CreationDate"); + + b.Property("ExpirationDate"); + + b.Property("Payload"); + + b.Property("Properties"); + + b.Property("ReferenceId") + .HasMaxLength(100); + + b.Property("Status") + .IsRequired() + .HasMaxLength(25); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(450); + + b.Property("Type") + .IsRequired() + .HasMaxLength(25); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId") + .IsUnique(); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens"); + }); + + modelBuilder.Entity("BTCPayServer.Data.AddressInvoiceData", b => + { + b.Property("Address") + .ValueGeneratedOnAdd(); + + b.Property("CreatedTime"); + + b.Property("InvoiceDataId"); + + b.HasKey("Address"); + + b.HasIndex("InvoiceDataId"); + + b.ToTable("AddressInvoices"); + }); + + modelBuilder.Entity("BTCPayServer.Data.APIKeyData", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(50); + + b.Property("StoreId") + .HasMaxLength(50); + + b.HasKey("Id"); + + b.HasIndex("StoreId"); + + b.ToTable("ApiKeys"); + }); + + modelBuilder.Entity("BTCPayServer.Data.AppData", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AppType"); + + b.Property("Created"); + + b.Property("Name"); + + b.Property("Settings"); + + b.Property("StoreDataId"); + + b.Property("TagAllInvoices"); + + b.HasKey("Id"); + + b.HasIndex("StoreDataId"); + + b.ToTable("Apps"); + }); + + modelBuilder.Entity("BTCPayServer.Data.HistoricalAddressInvoiceData", b => + { + b.Property("InvoiceDataId"); + + b.Property("Address"); + + b.Property("Assigned"); + + b.Property("CryptoCode"); + + b.Property("UnAssigned"); + + b.HasKey("InvoiceDataId", "Address"); + + b.ToTable("HistoricalAddressInvoices"); + }); + + modelBuilder.Entity("BTCPayServer.Data.InvoiceData", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Blob"); + + b.Property("Created"); + + b.Property("CustomerEmail"); + + b.Property("ExceptionStatus"); + + b.Property("ItemCode"); + + b.Property("OrderId"); + + b.Property("Status"); + + b.Property("StoreDataId"); + + b.HasKey("Id"); + + b.HasIndex("StoreDataId"); + + b.ToTable("Invoices"); + }); + + modelBuilder.Entity("BTCPayServer.Data.InvoiceEventData", b => + { + b.Property("InvoiceDataId"); + + b.Property("UniqueId"); + + b.Property("Message"); + + b.Property("Timestamp"); + + b.HasKey("InvoiceDataId", "UniqueId"); + + b.ToTable("InvoiceEvents"); + }); + + modelBuilder.Entity("BTCPayServer.Data.PairedSINData", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Facade"); + + b.Property("Label"); + + b.Property("PairingTime"); + + b.Property("SIN"); + + b.Property("StoreDataId"); + + b.HasKey("Id"); + + b.HasIndex("SIN"); + + b.HasIndex("StoreDataId"); + + b.ToTable("PairedSINData"); + }); + + modelBuilder.Entity("BTCPayServer.Data.PairingCodeData", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("DateCreated"); + + b.Property("Expiration"); + + b.Property("Facade"); + + b.Property("Label"); + + b.Property("SIN"); + + b.Property("StoreDataId"); + + b.Property("TokenValue"); + + b.HasKey("Id"); + + b.ToTable("PairingCodes"); + }); + + modelBuilder.Entity("BTCPayServer.Data.PaymentData", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Accounted"); + + b.Property("Blob"); + + b.Property("InvoiceDataId"); + + b.HasKey("Id"); + + b.HasIndex("InvoiceDataId"); + + b.ToTable("Payments"); + }); + + modelBuilder.Entity("BTCPayServer.Data.PendingInvoiceData", b => + { + b.Property("Id"); + + b.HasKey("Id"); + + b.ToTable("PendingInvoices"); + }); + + modelBuilder.Entity("BTCPayServer.Data.RefundAddressesData", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Blob"); + + b.Property("InvoiceDataId"); + + b.HasKey("Id"); + + b.HasIndex("InvoiceDataId"); + + b.ToTable("RefundAddresses"); + }); + + modelBuilder.Entity("BTCPayServer.Data.SettingData", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("BTCPayServer.Data.StoreData", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("DefaultCrypto"); + + b.Property("DerivationStrategies"); + + b.Property("DerivationStrategy"); + + b.Property("SpeedPolicy"); + + b.Property("StoreBlob"); + + b.Property("StoreCertificate"); + + b.Property("StoreName"); + + b.Property("StoreWebsite"); + + b.HasKey("Id"); + + b.ToTable("Stores"); + }); + + modelBuilder.Entity("BTCPayServer.Data.UserStore", b => + { + b.Property("ApplicationUserId"); + + b.Property("StoreDataId"); + + b.Property("Role"); + + b.HasKey("ApplicationUserId", "StoreDataId"); + + b.HasIndex("StoreDataId"); + + b.ToTable("UserStore"); + }); + + modelBuilder.Entity("BTCPayServer.Models.ApplicationUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("RequiresEmailConfirmation"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("BTCPayServer.Services.PaymentRequests.PaymentRequestData", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Blob"); + + b.Property("Status"); + + b.Property("StoreDataId"); + + b.HasKey("Id"); + + b.HasIndex("Status"); + + b.HasIndex("StoreDataId"); + + b.ToTable("PaymentRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50); + + b.Property("Description"); + + b.Property("DisplayName"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200); + + b.Property("Properties"); + + b.Property("Resources"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("OpenIddictScopes"); + }); + + modelBuilder.Entity("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdAuthorization", b => + { + b.HasOne("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdClient", "Application") + .WithMany("Authorizations") + .HasForeignKey("ApplicationId"); + }); + + modelBuilder.Entity("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdClient", b => + { + b.HasOne("BTCPayServer.Models.ApplicationUser", "ApplicationUser") + .WithMany("OpenIdClients") + .HasForeignKey("ApplicationUserId"); + }); + + modelBuilder.Entity("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdToken", b => + { + b.HasOne("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdClient", "Application") + .WithMany("Tokens") + .HasForeignKey("ApplicationId"); + + b.HasOne("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdAuthorization", "Authorization") + .WithMany("Tokens") + .HasForeignKey("AuthorizationId"); + }); + + modelBuilder.Entity("BTCPayServer.Data.AddressInvoiceData", b => + { + b.HasOne("BTCPayServer.Data.InvoiceData", "InvoiceData") + .WithMany("AddressInvoices") + .HasForeignKey("InvoiceDataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("BTCPayServer.Data.APIKeyData", b => + { + b.HasOne("BTCPayServer.Data.StoreData", "StoreData") + .WithMany("APIKeys") + .HasForeignKey("StoreId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("BTCPayServer.Data.AppData", b => + { + b.HasOne("BTCPayServer.Data.StoreData", "StoreData") + .WithMany("Apps") + .HasForeignKey("StoreDataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("BTCPayServer.Data.HistoricalAddressInvoiceData", b => + { + b.HasOne("BTCPayServer.Data.InvoiceData", "InvoiceData") + .WithMany("HistoricalAddressInvoices") + .HasForeignKey("InvoiceDataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("BTCPayServer.Data.InvoiceData", b => + { + b.HasOne("BTCPayServer.Data.StoreData", "StoreData") + .WithMany("Invoices") + .HasForeignKey("StoreDataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("BTCPayServer.Data.InvoiceEventData", b => + { + b.HasOne("BTCPayServer.Data.InvoiceData", "InvoiceData") + .WithMany("Events") + .HasForeignKey("InvoiceDataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("BTCPayServer.Data.PairedSINData", b => + { + b.HasOne("BTCPayServer.Data.StoreData", "StoreData") + .WithMany("PairedSINs") + .HasForeignKey("StoreDataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("BTCPayServer.Data.PaymentData", b => + { + b.HasOne("BTCPayServer.Data.InvoiceData", "InvoiceData") + .WithMany("Payments") + .HasForeignKey("InvoiceDataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("BTCPayServer.Data.PendingInvoiceData", b => + { + b.HasOne("BTCPayServer.Data.InvoiceData", "InvoiceData") + .WithMany("PendingInvoices") + .HasForeignKey("Id") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("BTCPayServer.Data.RefundAddressesData", b => + { + b.HasOne("BTCPayServer.Data.InvoiceData", "InvoiceData") + .WithMany("RefundAddresses") + .HasForeignKey("InvoiceDataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("BTCPayServer.Data.UserStore", b => + { + b.HasOne("BTCPayServer.Models.ApplicationUser", "ApplicationUser") + .WithMany("UserStores") + .HasForeignKey("ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("BTCPayServer.Data.StoreData", "StoreData") + .WithMany("UserStores") + .HasForeignKey("StoreDataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("BTCPayServer.Services.PaymentRequests.PaymentRequestData", b => + { + b.HasOne("BTCPayServer.Data.StoreData", "StoreData") + .WithMany("PaymentRequests") + .HasForeignKey("StoreDataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("BTCPayServer.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("BTCPayServer.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("BTCPayServer.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("BTCPayServer.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/BTCPayServer/Migrations/20190225091644_AddOpenIddict.cs b/BTCPayServer/Migrations/20190225091644_AddOpenIddict.cs new file mode 100644 index 000000000..e2181ce56 --- /dev/null +++ b/BTCPayServer/Migrations/20190225091644_AddOpenIddict.cs @@ -0,0 +1,167 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace BTCPayServer.Migrations +{ + public partial class AddOpenIddict : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "OpenIddictApplications", + columns: table => new + { + ClientId = table.Column(maxLength: 100, nullable: false), + ClientSecret = table.Column(nullable: true), + ConcurrencyToken = table.Column(maxLength: 50, nullable: true), + ConsentType = table.Column(nullable: true), + DisplayName = table.Column(nullable: true), + Id = table.Column(nullable: false), + Permissions = table.Column(nullable: true), + PostLogoutRedirectUris = table.Column(nullable: true), + Properties = table.Column(nullable: true), + RedirectUris = table.Column(nullable: true), + Type = table.Column(maxLength: 25, nullable: false), + ApplicationUserId = table.Column(nullable: true) + }, + 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); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictScopes", + columns: table => new + { + ConcurrencyToken = table.Column(maxLength: 50, nullable: true), + Description = table.Column(nullable: true), + DisplayName = table.Column(nullable: true), + Id = table.Column(nullable: false), + Name = table.Column(maxLength: 200, nullable: false), + Properties = table.Column(nullable: true), + Resources = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_OpenIddictScopes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictAuthorizations", + columns: table => new + { + ApplicationId = table.Column(nullable: true), + ConcurrencyToken = table.Column(maxLength: 50, nullable: true), + Id = table.Column(nullable: false), + Properties = table.Column(nullable: true), + Scopes = table.Column(nullable: true), + Status = table.Column(maxLength: 25, nullable: false), + Subject = table.Column(maxLength: 450, nullable: false), + Type = table.Column(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); + }); + + migrationBuilder.CreateTable( + name: "OpenIddictTokens", + columns: table => new + { + ApplicationId = table.Column(nullable: true), + AuthorizationId = table.Column(nullable: true), + ConcurrencyToken = table.Column(maxLength: 50, nullable: true), + CreationDate = table.Column(nullable: true), + ExpirationDate = table.Column(nullable: true), + Id = table.Column(nullable: false), + Payload = table.Column(nullable: true), + Properties = table.Column(nullable: true), + ReferenceId = table.Column(maxLength: 100, nullable: true), + Status = table.Column(maxLength: 25, nullable: false), + Subject = table.Column(maxLength: 450, nullable: false), + Type = table.Column(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); + }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictApplications_ApplicationUserId", + table: "OpenIddictApplications", + column: "ApplicationUserId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictApplications_ClientId", + table: "OpenIddictApplications", + column: "ClientId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictAuthorizations_ApplicationId_Status_Subject_Type", + table: "OpenIddictAuthorizations", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictScopes_Name", + table: "OpenIddictScopes", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_AuthorizationId", + table: "OpenIddictTokens", + column: "AuthorizationId"); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ReferenceId", + table: "OpenIddictTokens", + column: "ReferenceId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_OpenIddictTokens_ApplicationId_Status_Subject_Type", + table: "OpenIddictTokens", + columns: new[] { "ApplicationId", "Status", "Subject", "Type" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "OpenIddictScopes"); + + migrationBuilder.DropTable( + name: "OpenIddictTokens"); + + migrationBuilder.DropTable( + name: "OpenIddictAuthorizations"); + + migrationBuilder.DropTable( + name: "OpenIddictApplications"); + } + } +} diff --git a/BTCPayServer/Migrations/ApplicationDbContextModelSnapshot.cs b/BTCPayServer/Migrations/ApplicationDbContextModelSnapshot.cs index 4ba99f2fe..945d5f436 100644 --- a/BTCPayServer/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/BTCPayServer/Migrations/ApplicationDbContextModelSnapshot.cs @@ -16,6 +16,131 @@ namespace BTCPayServer.Migrations modelBuilder .HasAnnotation("ProductVersion", "2.1.8-servicing-32085"); + modelBuilder.Entity("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ApplicationId"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50); + + b.Property("Properties"); + + b.Property("Scopes"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(25); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(450); + + b.Property("Type") + .IsRequired() + .HasMaxLength(25); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations"); + }); + + modelBuilder.Entity("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdClient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ApplicationUserId"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(100); + + b.Property("ClientSecret"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50); + + b.Property("ConsentType"); + + b.Property("DisplayName"); + + b.Property("Permissions"); + + b.Property("PostLogoutRedirectUris"); + + b.Property("Properties"); + + b.Property("RedirectUris"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(25); + + b.HasKey("Id"); + + b.HasIndex("ApplicationUserId"); + + b.HasIndex("ClientId") + .IsUnique(); + + b.ToTable("OpenIddictApplications"); + }); + + modelBuilder.Entity("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ApplicationId"); + + b.Property("AuthorizationId"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50); + + b.Property("CreationDate"); + + b.Property("ExpirationDate"); + + b.Property("Payload"); + + b.Property("Properties"); + + b.Property("ReferenceId") + .HasMaxLength(100); + + b.Property("Status") + .IsRequired() + .HasMaxLength(25); + + b.Property("Subject") + .IsRequired() + .HasMaxLength(450); + + b.Property("Type") + .IsRequired() + .HasMaxLength(25); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId") + .IsUnique(); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens"); + }); + modelBuilder.Entity("BTCPayServer.Data.AddressInvoiceData", b => { b.Property("Address") @@ -500,6 +625,60 @@ namespace BTCPayServer.Migrations b.ToTable("AspNetUserTokens"); }); + modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50); + + b.Property("Description"); + + b.Property("DisplayName"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200); + + b.Property("Properties"); + + b.Property("Resources"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("OpenIddictScopes"); + }); + + modelBuilder.Entity("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdAuthorization", b => + { + b.HasOne("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdClient", "Application") + .WithMany("Authorizations") + .HasForeignKey("ApplicationId"); + }); + + modelBuilder.Entity("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdClient", b => + { + b.HasOne("BTCPayServer.Models.ApplicationUser", "ApplicationUser") + .WithMany("OpenIdClients") + .HasForeignKey("ApplicationUserId"); + }); + + modelBuilder.Entity("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdToken", b => + { + b.HasOne("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdClient", "Application") + .WithMany("Tokens") + .HasForeignKey("ApplicationId"); + + b.HasOne("BTCPayServer.Authentication.OpenId.Models.BTCPayOpenIdAuthorization", "Authorization") + .WithMany("Tokens") + .HasForeignKey("AuthorizationId"); + }); + modelBuilder.Entity("BTCPayServer.Data.AddressInvoiceData", b => { b.HasOne("BTCPayServer.Data.InvoiceData", "InvoiceData") diff --git a/BTCPayServer/Models/ApplicationUser.cs b/BTCPayServer/Models/ApplicationUser.cs index 7721e2b1b..9c87bb965 100644 --- a/BTCPayServer/Models/ApplicationUser.cs +++ b/BTCPayServer/Models/ApplicationUser.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using BTCPayServer.Authentication.OpenId.Models; using Microsoft.AspNetCore.Identity; using BTCPayServer.Data; using BTCPayServer.Services.U2F.Models; @@ -23,6 +24,8 @@ namespace BTCPayServer.Models get; set; } + public List OpenIdClients { get; set; } + public List StoredFiles { get; diff --git a/BTCPayServer/Security/Policies.cs b/BTCPayServer/Security/Policies.cs index f9ce9a1f7..c7dd4c16e 100644 --- a/BTCPayServer/Security/Policies.cs +++ b/BTCPayServer/Security/Policies.cs @@ -8,6 +8,7 @@ namespace BTCPayServer.Security { public static class Policies { + public const string BitpayAuthentication = "Bitpay.Auth"; public const string CookieAuthentication = "Identity.Application"; public static AuthorizationOptions AddBTCPayPolicies(this AuthorizationOptions options) @@ -31,10 +32,10 @@ namespace BTCPayServer.Security { public const string Key = "btcpay.store.canmodifystoresettings"; } - public class CanCreateInvoice { public const string Key = "btcpay.store.cancreateinvoice"; } + } } diff --git a/BTCPayServer/Views/Account/Login.cshtml b/BTCPayServer/Views/Account/Login.cshtml index 84cf78589..6d6e76760 100644 --- a/BTCPayServer/Views/Account/Login.cshtml +++ b/BTCPayServer/Views/Account/Login.cshtml @@ -1,8 +1,4 @@ -@using System.Collections.Generic -@using System.Linq -@using Microsoft.AspNetCore.Http -@using Microsoft.AspNetCore.Http.Authentication -@model LoginViewModel +@model LoginViewModel @inject SignInManager SignInManager @{ @@ -55,35 +51,6 @@
-
-

Use another service to log in.

-
- @{ - var loginProviders = (await SignInManager.GetExternalAuthenticationSchemesAsync()).ToList(); - if(loginProviders.Count == 0) - { -
-

- There are no external authentication services configured. See this article - for details on setting up this ASP.NET application to support logging in via external services. -

-
- } - else - { -
-
-

- @foreach(var provider in loginProviders) - { - - } -

-
-
- } - } -