From 5d1413f733b168ec8c34f0370ad878591d287fc4 Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Thu, 11 Apr 2024 11:06:08 +0200 Subject: [PATCH] Support registration --- BTCPayApp.CommonServer/AppInstanceInfo.cs | 12 ++++ BTCPayApp.CommonServer/SignupRequest.cs | 12 ++++ BTCPayApp.CommonServer/SignupResult.cs | 8 +++ BTCPayServer/App/BtcPayAppController.cs | 73 ++++++++++++++++++++++- BTCPayServer/Services/ServerSettings.cs | 4 +- 5 files changed, 104 insertions(+), 5 deletions(-) create mode 100644 BTCPayApp.CommonServer/AppInstanceInfo.cs create mode 100644 BTCPayApp.CommonServer/SignupRequest.cs create mode 100644 BTCPayApp.CommonServer/SignupResult.cs diff --git a/BTCPayApp.CommonServer/AppInstanceInfo.cs b/BTCPayApp.CommonServer/AppInstanceInfo.cs new file mode 100644 index 000000000..c739c914b --- /dev/null +++ b/BTCPayApp.CommonServer/AppInstanceInfo.cs @@ -0,0 +1,12 @@ +namespace BTCPayApp.CommonServer; + +public class AppInstanceInfo +{ + public string BaseUrl { get; set; } + public string ServerName { get; set; } = "BTCPay Server"; + public string? ContactUrl { get; set; } + public string? LogoUrl { get; set; } + public string? CustomThemeCssUrl { get; set; } + public string? CustomThemeExtension { get; set; } + public bool RegistrationEnabled { get; set; } +} diff --git a/BTCPayApp.CommonServer/SignupRequest.cs b/BTCPayApp.CommonServer/SignupRequest.cs new file mode 100644 index 000000000..fe9e189cb --- /dev/null +++ b/BTCPayApp.CommonServer/SignupRequest.cs @@ -0,0 +1,12 @@ +using System.ComponentModel.DataAnnotations; + +namespace BTCPayApp.CommonServer; + +public class SignupRequest +{ + [Required] + public string Email { get; init; } + + [Required] + public string Password { get; init; } +} diff --git a/BTCPayApp.CommonServer/SignupResult.cs b/BTCPayApp.CommonServer/SignupResult.cs new file mode 100644 index 000000000..ab0ad80c5 --- /dev/null +++ b/BTCPayApp.CommonServer/SignupResult.cs @@ -0,0 +1,8 @@ +namespace BTCPayApp.CommonServer; + +public class SignupResult +{ + public string Email { get; set; } + public bool RequiresConfirmedEmail { get; set; } + public bool RequiresUserApproval { get; set; } +} diff --git a/BTCPayServer/App/BtcPayAppController.cs b/BTCPayServer/App/BtcPayAppController.cs index 1a70e7f92..04d12301b 100644 --- a/BTCPayServer/App/BtcPayAppController.cs +++ b/BTCPayServer/App/BtcPayAppController.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Threading.Tasks; using BTCPayApp.CommonServer; using BTCPayServer.Abstractions.Constants; +using BTCPayServer.Abstractions.Contracts; using BTCPayServer.Abstractions.Extensions; using BTCPayServer.Client; using BTCPayServer.Common; @@ -43,9 +44,77 @@ public class BtcPayAppController( UserManager userManager, TimeProvider timeProvider, PaymentMethodHandlerDictionary handlers, + IFileService fileService, + ISettingsRepository settingsRepository, IOptionsMonitor bearerTokenOptions) : Controller { + [AllowAnonymous] + [HttpGet("instance")] + public async Task, NotFound>> Instance() + { + var serverSettings = await settingsRepository.GetSettingAsync() ?? new ServerSettings(); + var policiesSettings = await settingsRepository.GetSettingAsync() ?? new PoliciesSettings(); + var themeSettings = await settingsRepository.GetSettingAsync() ?? new ThemeSettings(); + + return TypedResults.Ok(new AppInstanceInfo + { + BaseUrl = Request.GetAbsoluteRoot(), + ServerName = serverSettings.ServerName, + ContactUrl = serverSettings.ContactUrl, + RegistrationEnabled = policiesSettings.EnableRegistration, + CustomThemeExtension = themeSettings.CustomTheme ? themeSettings.CustomThemeExtension.ToString() : null, + CustomThemeCssUrl = themeSettings.CustomTheme && !string.IsNullOrEmpty(themeSettings.CustomThemeFileId) + ? await fileService.GetFileUrl(Request.GetAbsoluteRootUri(), themeSettings.CustomThemeFileId) + : null, + LogoUrl = !string.IsNullOrEmpty(themeSettings.LogoFileId) + ? await fileService.GetFileUrl(Request.GetAbsoluteRootUri(), themeSettings.LogoFileId) + : null + }); + } + + [AllowAnonymous] + [HttpPost("register")] + [RateLimitsFilter(ZoneLimits.Login, Scope = RateLimitsScope.RemoteAddress)] + public async Task, ValidationProblem, ProblemHttpResult>> Register(SignupRequest signup) + { + var policiesSettings = await settingsRepository.GetSettingAsync() ?? new PoliciesSettings(); + if (policiesSettings.LockSubscription) + return TypedResults.Problem("This instance does not allow public user registration", statusCode: 406); + + var errorMessage = "Invalid signup attempt."; + if (ModelState.IsValid) + { + var user = new ApplicationUser + { + UserName = signup.Email, + Email = signup.Email, + RequiresEmailConfirmation = policiesSettings.RequiresConfirmedEmail, + RequiresApproval = policiesSettings.RequiresUserApproval, + Created = DateTimeOffset.UtcNow + }; + var result = await userManager.CreateAsync(user, signup.Password); + if (result.Succeeded) + { + eventAggregator.Publish(new UserRegisteredEvent + { + RequestUri = Request.GetAbsoluteRootUri(), + User = user + }); + + var response = new SignupResult + { + Email = user.Email, + RequiresConfirmedEmail = policiesSettings.RequiresConfirmedEmail && !user.EmailConfirmed, + RequiresUserApproval = policiesSettings.RequiresUserApproval && !user.Approved + }; + return TypedResults.Ok(response); + } + errorMessage = result.ToString(); + } + return TypedResults.Problem(errorMessage, statusCode: 400); + } + [AllowAnonymous] [HttpPost("login")] [RateLimitsFilter(ZoneLimits.Login, Scope = RateLimitsScope.RemoteAddress)] @@ -122,8 +191,8 @@ public class BtcPayAppController( return Results.Unauthorized(); } - [HttpGet("info")] - public async Task, ValidationProblem, NotFound>> Info() + [HttpGet("user")] + public async Task, NotFound>> UserInfo() { var user = await userManager.GetUserAsync(User); if (user == null) return TypedResults.NotFound(); diff --git a/BTCPayServer/Services/ServerSettings.cs b/BTCPayServer/Services/ServerSettings.cs index 9ca61a539..e545603f6 100644 --- a/BTCPayServer/Services/ServerSettings.cs +++ b/BTCPayServer/Services/ServerSettings.cs @@ -1,13 +1,11 @@ using System.ComponentModel.DataAnnotations; -using Microsoft.AspNetCore.Http; -using Newtonsoft.Json; namespace BTCPayServer.Services; public class ServerSettings { [Display(Name = "Server Name")] - public string ServerName { get; set; } + public string ServerName { get; set; } = "BTCPay Server"; [Display(Name = "Contact URL")] public string ContactUrl { get; set; }