Support registration

This commit is contained in:
Dennis Reimann 2024-04-11 11:06:08 +02:00
parent 395abe0e5c
commit 5d1413f733
No known key found for this signature in database
GPG key ID: 5009E1797F03F8D0
5 changed files with 104 additions and 5 deletions

View file

@ -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; }
}

View file

@ -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; }
}

View file

@ -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; }
}

View file

@ -4,6 +4,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayApp.CommonServer; using BTCPayApp.CommonServer;
using BTCPayServer.Abstractions.Constants; using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Abstractions.Contracts;
using BTCPayServer.Abstractions.Extensions; using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Client; using BTCPayServer.Client;
using BTCPayServer.Common; using BTCPayServer.Common;
@ -43,9 +44,77 @@ public class BtcPayAppController(
UserManager<ApplicationUser> userManager, UserManager<ApplicationUser> userManager,
TimeProvider timeProvider, TimeProvider timeProvider,
PaymentMethodHandlerDictionary handlers, PaymentMethodHandlerDictionary handlers,
IFileService fileService,
ISettingsRepository settingsRepository,
IOptionsMonitor<BearerTokenOptions> bearerTokenOptions) IOptionsMonitor<BearerTokenOptions> bearerTokenOptions)
: Controller : Controller
{ {
[AllowAnonymous]
[HttpGet("instance")]
public async Task<Results<Ok<AppInstanceInfo>, NotFound>> Instance()
{
var serverSettings = await settingsRepository.GetSettingAsync<ServerSettings>() ?? new ServerSettings();
var policiesSettings = await settingsRepository.GetSettingAsync<PoliciesSettings>() ?? new PoliciesSettings();
var themeSettings = await settingsRepository.GetSettingAsync<ThemeSettings>() ?? 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<Results<Ok<SignupResult>, ValidationProblem, ProblemHttpResult>> Register(SignupRequest signup)
{
var policiesSettings = await settingsRepository.GetSettingAsync<PoliciesSettings>() ?? 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] [AllowAnonymous]
[HttpPost("login")] [HttpPost("login")]
[RateLimitsFilter(ZoneLimits.Login, Scope = RateLimitsScope.RemoteAddress)] [RateLimitsFilter(ZoneLimits.Login, Scope = RateLimitsScope.RemoteAddress)]
@ -122,8 +191,8 @@ public class BtcPayAppController(
return Results.Unauthorized(); return Results.Unauthorized();
} }
[HttpGet("info")] [HttpGet("user")]
public async Task<Results<Ok<AppUserInfo>, ValidationProblem, NotFound>> Info() public async Task<Results<Ok<AppUserInfo>, NotFound>> UserInfo()
{ {
var user = await userManager.GetUserAsync(User); var user = await userManager.GetUserAsync(User);
if (user == null) return TypedResults.NotFound(); if (user == null) return TypedResults.NotFound();

View file

@ -1,13 +1,11 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
namespace BTCPayServer.Services; namespace BTCPayServer.Services;
public class ServerSettings public class ServerSettings
{ {
[Display(Name = "Server Name")] [Display(Name = "Server Name")]
public string ServerName { get; set; } public string ServerName { get; set; } = "BTCPay Server";
[Display(Name = "Contact URL")] [Display(Name = "Contact URL")]
public string ContactUrl { get; set; } public string ContactUrl { get; set; }